Stretched button in DiagonalLayout - java

I have a small problem with the layout diagonalLayout proposed on the site of oracle ...
In fact I would just stretch the last button on the width of my screen while keeping the layout and I can not, but I've tried this code:
public void stretchLastComponent(Container container){
int nComps = container.getComponentCount();
Component c = container.getComponent(nComps-1);
c.setSize(container.getWidth(), c.getHeight());
I also use repaint () and revalidate (), but without result.
Here is the class used (it was an imposed job I can not change the layout):
DiagonalLayout.java
And I also supplied in code for simplicity in the forum:
package layout;
/*
* 1.2+ version. Used by CustomLayoutDemo.java.
*/
import java.awt.*;
public class DiagonalLayout implements LayoutManager {
private int vgap;
private int minWidth = 0, minHeight = 0;
private int preferredWidth = 0, preferredHeight = 0;
private boolean sizeUnknown = true;
public DiagonalLayout() {
this(5);
}
public DiagonalLayout(int v) {
vgap = v;
}
/* Required by LayoutManager. */
public void addLayoutComponent(String name, Component comp) {
}
/* Required by LayoutManager. */
public void removeLayoutComponent(Component comp) {
}
private void setSizes(Container parent) {
int nComps = parent.getComponentCount();
Dimension d = null;
//Reset preferred/minimum width and height.
preferredWidth = 0;
preferredHeight = 0;
minWidth = 0;
minHeight = 0;
for (int i = 0; i < nComps; i++) {
Component c = parent.getComponent(i);
if (c.isVisible()) {
d = c.getPreferredSize();
if (i > 0) {
preferredWidth += d.width/2;
preferredHeight += vgap;
} else {
preferredWidth = d.width;
}
preferredHeight += d.height;
minWidth = Math.max(c.getMinimumSize().width,
minWidth);
minHeight = preferredHeight;
}
}
}
/* Required by LayoutManager. */
public Dimension preferredLayoutSize(Container parent) {
Dimension dim = new Dimension(0, 0);
int nComps = parent.getComponentCount();
setSizes(parent);
//Always add the container's insets!
Insets insets = parent.getInsets();
dim.width = preferredWidth
+ insets.left + insets.right;
dim.height = preferredHeight
+ insets.top + insets.bottom;
sizeUnknown = false;
return dim;
}
/* Required by LayoutManager. */
public Dimension minimumLayoutSize(Container parent) {
Dimension dim = new Dimension(0, 0);
int nComps = parent.getComponentCount();
//Always add the container's insets!
Insets insets = parent.getInsets();
dim.width = minWidth
+ insets.left + insets.right;
dim.height = minHeight
+ insets.top + insets.bottom;
sizeUnknown = false;
return dim;
}
/* Required by LayoutManager. */
/*
* This is called when the panel is first displayed,
* and every time its size changes.
* Note: You CAN'T assume preferredLayoutSize or
* minimumLayoutSize will be called -- in the case
* of applets, at least, they probably won't be.
*/
public void layoutContainer(Container parent) {
Insets insets = parent.getInsets();
int maxWidth = parent.getWidth()
- (insets.left + insets.right);
int maxHeight = parent.getHeight()
- (insets.top + insets.bottom);
int nComps = parent.getComponentCount();
int previousWidth = 0, previousHeight = 0;
int x = 0, y = insets.top;
int rowh = 0, start = 0;
int xFudge = 0, yFudge = 0;
boolean oneColumn = false;
// Go through the components' sizes, if neither
// preferredLayoutSize nor minimumLayoutSize has
// been called.
if (sizeUnknown) {
setSizes(parent);
}
if (maxWidth <= minWidth) {
oneColumn = true;
}
if (maxWidth != preferredWidth) {
xFudge = (maxWidth - preferredWidth)/(nComps - 1);
}
if (maxHeight > preferredHeight) {
yFudge = (maxHeight - preferredHeight)/(nComps - 1);
}
for (int i = 0 ; i < nComps ; i++) {
Component c = parent.getComponent(i);
if (c.isVisible()) {
Dimension d = c.getPreferredSize();
// increase x and y, if appropriate
if (i > 0) {
if (!oneColumn) {
x += previousWidth/2 + xFudge;
}
y += previousHeight + vgap + yFudge;
}
// If x is too large,
if ((!oneColumn) &&
(x + d.width) >
(parent.getWidth() - insets.right)) {
// reduce x to a reasonable number.
x = parent.getWidth()
- insets.bottom - d.width;
}
// If y is too large,
if ((y + d.height)
> (parent.getHeight() - insets.bottom)) {
// do nothing.
// Another choice would be to do what we do to x.
}
// Set the component's size and position.
c.setBounds(x, y, d.width, d.height);
previousWidth = d.width;
previousHeight = d.height;
}
}
}
public String toString() {
String str = "";
return getClass().getName() + "[vgap=" + vgap + str + "]";
}
}
Thank you in advance.

You can't/shouldn't change the size/position of any component which under the control of a layout manager, the next time the container is validated (laid out) those values will be rest by the layout manager...
Now having said that, since you have access to the source code of the layout manager, you have the ability to effect how it makes it's decisions...
By simply adding this into the layoutContainer method, right before c.setBounds(x, y, d.width, d.height);
if (i == nComps - 1) {
d.width = parent.getWidth();
x = 0;
}
I was able to achieve this...
UPDATED after feedback
I've fudged the layout code a little to allow the layout to perform the way you image suggest...
public class TestLayout14 {
public static void main(String[] args) {
new TestLayout14();
}
public TestLayout14() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JPanel content = new JPanel(new BorderLayout());
LayoutPane layoutPane = new LayoutPane();
content.add(layoutPane);
content.add(new ControlPane(layoutPane), BorderLayout.SOUTH);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class LayoutPane extends JPanel {
public LayoutPane() {
setLayout(new DiagonalLayout());
add(new JLabel("Test 01"));
add(new JLabel("Test 02"));
add(new JLabel("Test 03"));
add(new JButton("Test 04"));
}
}
public class ControlPane extends JPanel {
private JTextField fieldGap;
private JCheckBox majorDiag;
private JCheckBox streatchLast;
private LayoutPane layoutPane;
public ControlPane(LayoutPane pane) {
layoutPane = pane;
setBorder(new CompoundBorder(new EmptyBorder(4, 0, 0, 0), new MatteBorder(1, 0, 0, 0, Color.GRAY)));
fieldGap = new JTextField(Integer.toString(((DiagonalLayout)layoutPane.getLayout()).getVgap()), 4);
majorDiag = new JCheckBox("Major Diagnal");
streatchLast = new JCheckBox("Last Component Stretched");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 0;
gbc.gridy = 0;
add(new JLabel("Diagnal Gap: "), gbc);
gbc.gridx++;
add(fieldGap, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(majorDiag, gbc);
gbc.gridy++;
add(streatchLast, gbc);
fieldGap.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
((DiagonalLayout) layoutPane.getLayout()).setVgap(Integer.parseInt(fieldGap.getText()));
layoutPane.invalidate();
layoutPane.revalidate();
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
streatchLast.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
((DiagonalLayout) layoutPane.getLayout()).setStreatchLast(streatchLast.isSelected());
layoutPane.invalidate();
layoutPane.revalidate();
}
});
}
}
public class DiagonalLayout implements LayoutManager {
private int vgap;
private int minWidth = 0, minHeight = 0;
private int preferredWidth = 0, preferredHeight = 0;
private boolean sizeUnknown = true;
private boolean streatchLast = false;
public DiagonalLayout() {
this(5);
}
public DiagonalLayout(int v) {
vgap = v;
}
public void setVgap(int vgap) {
this.vgap = vgap;
}
public int getVgap() {
return vgap;
}
public void setStreatchLast(boolean streatchLast) {
this.streatchLast = streatchLast;
}
public boolean isStreatchLast() {
return streatchLast;
}
/* Required by LayoutManager. */
public void addLayoutComponent(String name, Component comp) {
}
/* Required by LayoutManager. */
public void removeLayoutComponent(Component comp) {
}
private void setSizes(Container parent) {
int nComps = parent.getComponentCount();
Dimension d = null;
//Reset preferred/minimum width and height.
preferredWidth = 0;
preferredHeight = 0;
minWidth = 0;
minHeight = 0;
for (int i = 0; i < nComps; i++) {
Component c = parent.getComponent(i);
if (c.isVisible()) {
d = c.getPreferredSize();
if (i > 0) {
preferredWidth += d.width / 2;
preferredHeight += vgap;
} else {
preferredWidth = d.width;
}
preferredHeight += d.height;
minWidth = Math.max(c.getMinimumSize().width,
minWidth);
minHeight = preferredHeight;
}
}
}
/* Required by LayoutManager. */
public Dimension preferredLayoutSize(Container parent) {
Dimension dim = new Dimension(0, 0);
int nComps = parent.getComponentCount();
setSizes(parent);
//Always add the container's insets!
Insets insets = parent.getInsets();
dim.width = preferredWidth
+ insets.left + insets.right;
dim.height = preferredHeight
+ insets.top + insets.bottom;
sizeUnknown = false;
return dim;
}
/* Required by LayoutManager. */
public Dimension minimumLayoutSize(Container parent) {
Dimension dim = new Dimension(0, 0);
int nComps = parent.getComponentCount();
//Always add the container's insets!
Insets insets = parent.getInsets();
dim.width = minWidth
+ insets.left + insets.right;
dim.height = minHeight
+ insets.top + insets.bottom;
sizeUnknown = false;
return dim;
}
/* Required by LayoutManager. */
/*
* This is called when the panel is first displayed,
* and every time its size changes.
* Note: You CAN'T assume preferredLayoutSize or
* minimumLayoutSize will be called -- in the case
* of applets, at least, they probably won't be.
*/
public void layoutContainer(Container parent) {
Insets insets = parent.getInsets();
int maxWidth = parent.getWidth()
- (insets.left + insets.right);
int maxHeight = parent.getHeight()
- (insets.top + insets.bottom);
int nComps = parent.getComponentCount();
int previousWidth = 0, previousHeight = 0;
int x = 0, y = insets.top;
int rowh = 0, start = 0;
int xFudge = 0, yFudge = 0;
boolean oneColumn = false;
// Go through the components' sizes, if neither
// preferredLayoutSize nor minimumLayoutSize has
// been called.
if (sizeUnknown) {
setSizes(parent);
}
if (maxWidth <= minWidth) {
oneColumn = true;
}
// if (maxWidth != preferredWidth) {
// xFudge = (maxWidth - preferredWidth) / (nComps - 1);
// }
//
// if (maxHeight > preferredHeight) {
// yFudge = (maxHeight - preferredHeight) / (nComps - 1);
// }
for (int i = 0; i < nComps; i++) {
Component c = parent.getComponent(i);
if (c.isVisible()) {
Dimension d = c.getPreferredSize();
// increase x and y, if appropriate
if (i > 0) {
if (!oneColumn) {
x += previousWidth / 2 + xFudge;
}
y += previousHeight + vgap + yFudge;
}
// If x is too large,
if ((!oneColumn)
&& (x + d.width)
> (parent.getWidth() - insets.right)) {
// reduce x to a reasonable number.
x = parent.getWidth()
- insets.bottom - d.width;
}
// If y is too large,
if ((y + d.height)
> (parent.getHeight() - insets.bottom)) {
// do nothing.
// Another choice would be to do what we do to x.
}
if (isStreatchLast() && i == nComps - 1) {
d.width = parent.getWidth() - x;
}
// Set the component's size and position.
c.setBounds(x, y, d.width, d.height);
previousWidth = d.width;
previousHeight = d.height;
}
}
}
public String toString() {
String str = "";
return getClass().getName() + "[vgap=" + vgap + str + "]";
}
}
}

Related

JTextField java?

My Task:
Create an application that displays a Hangman graphic for 10 steps. This graphic should be controllable via a text field and a slider (in the range 0-10) for test purposes. The text box updates the graph as soon as the value is changed and does not wait until the Enter key is pressed. If an invalid value is entered in the text field, then an error message is displayed instead of the graphic (with the method drawString text can also be "drawn"), if there should be no value there, then the graphic should remain empty.
In my program, the change of the graphics on the JSlider works fine, but the input via the text field causes no change and the check when entering an incorrect value, I tried, but then nothing is displayed. I do not understand what's wrong because the JTextField approach is the same as JSlider ...
I have put the source code of both classes down below.
First Class:
Imports, Package...
public class HangmanFrame extends JFrame{
public HangmanFrame(){
super("Hangman");
HangmanPanel panel = new HangmanPanel();
JPanel mainPanel = new JPanel();
this.add(mainPanel);
mainPanel.setLayout(new BorderLayout());
JTextField t = new JTextField();
t.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void changedUpdate(DocumentEvent arg0) {
try{
Integer.parseInt(t.getText());
}
catch(NumberFormatException ex){
System.out.println(ex.getMessage());
}
panel.repaint();
}
#Override
public void insertUpdate(DocumentEvent arg0) {
try{
Integer.parseInt(t.getText());
}
catch(NumberFormatException ex){
System.out.println(ex.getMessage());
}
panel.repaint();
}
#Override
public void removeUpdate(DocumentEvent arg0) {
try{
Integer.parseInt(t.getText());
}
catch(NumberFormatException ex){
System.out.println(ex.getMessage());
}
panel.repaint();
}
});
JSlider s = new JSlider(JSlider.HORIZONTAL, 0, 10, 0);
s.addChangeListener(new ChangeListener(){
#Override
public void stateChanged(ChangeEvent arg0) {
panel.repaint();
}
});
panel.setSlider(s);
panel.setTextField(t);
mainPanel.add(panel, BorderLayout.CENTER);
mainPanel.add(s, BorderLayout.PAGE_END);
mainPanel.add(t, BorderLayout.PAGE_START);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setSize(300,500);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
new HangmanFrame();
}
}
Second Class:
public class HangmanPanel extends JPanel {
private JSlider slider;
private JTextField field; //Height 500, Width 300
public void paintComponent(Graphics g){
super.paintComponent(g);
int sliderValue = slider.getValue();
String fieldValue = field.getText();
//int fieldInt = Integer.parseInt(fieldValue);
g.drawLine(0, super.getWidth() + 99, super.getHeight(), super.getWidth() + 99);
if(sliderValue == 0 || fieldValue.equals("0")){
return;
}
g.setColor(new Color(205,133,63));
int xArc = this.getWidth() / 20;
int yArc = this.getHeight() - this.getHeight() / 5;
int arcWidth = this.getWidth() / 2;
int arcHeight = this.getHeight() / 5;
g.fillArc(xArc, yArc, arcWidth, arcHeight, 0, 180);
if(sliderValue == 1 || fieldValue.equals("1")){
return;
}
g.setColor(Color.BLACK);
int x1Line = xArc + arcWidth / 2;
int x2Line = x1Line;
int y1Line = yArc;
int y2Line = this.getHeight() / 6;
g.drawLine(x1Line, y1Line, x2Line, y2Line);
if(sliderValue == 2 || fieldValue.equals("2")){
return;
}
int x3Line = x1Line;
int x4Line = x3Line + (this.getWidth() / 3) + 20;
int y3Line = y2Line;
int y4Line = y3Line;
g.drawLine(x3Line, y3Line, x4Line, y4Line);
if(sliderValue == 3 || fieldValue.equals("3")){
return;
}
int x5Line = x4Line;
int x6Line = x5Line;
int y5Line = y4Line;
int y6Line = y5Line + this.getWidth() / 5; // + 60
g.drawLine(x5Line, y5Line, x6Line, y6Line);
if(sliderValue == 4 || fieldValue.equals("4")){
return;
}
g.setColor(new Color(255, 221, 204));
g.fillOval(x6Line - this.getHeight() / 20, y6Line, this.getHeight() / 10, this.getHeight() / 10); // -25, ...,50, 50
if(sliderValue == 5 || fieldValue.equals("5")){
return;
}
g.setColor(Color.BLUE);
g.fillOval((int) ((int) x6Line - this.getHeight() / 14.7) , (int) (y6Line + this.getHeight() / 10.41), (int)(this.getHeight() / 7.14), (int)(this.getHeight() / 4.16)); // 34, 48, 70, 120
if(sliderValue == 6 || fieldValue.equals("6")){
return;
}
int x7Line = x6Line + (int)(this.getHeight() / 17.85); // 28
int x8Line = x7Line + (int)(this.getHeight() / 12.5); // 40
int y7Line = y6Line + (int)(this.getHeight() / 7.14); // 70
int y8Line = y7Line - (int)(this.getHeight() / 14.28); // 35
g.setColor(Color.BLACK);
g.drawLine(x7Line, y7Line, x8Line, y8Line);
if(sliderValue == 7 || fieldValue.equals("7")){
return;
}
int x9Line = x7Line - (int)(this.getHeight() / 9.43); // 53
int x10Line = x9Line - (int)(this.getHeight() / 14.28); // 35
int y9Line = y7Line;
int y10Line = y8Line;
g.drawLine(x9Line, y9Line, x10Line, y10Line);
if(sliderValue == 8 || fieldValue.equals("8")){
return;
}
int x11Line = x7Line;
int x12Line = x8Line;
int y11Line = y7Line + (int)(this.getHeight() / 6.66); // 75
int y12Line = y8Line + (int)(this.getHeight() / 3.33); // 150
g.drawLine(x11Line, y11Line, x12Line, y12Line);
if(sliderValue == 9 || fieldValue.equals("9")){
return;
}
int x13Line = x9Line;
int x14Line = x10Line;
int y13Line = y11Line;
int y14Line = y12Line;
g.drawLine(x13Line, y13Line, x14Line, y14Line);
}
public void setSlider(JSlider slider){
this.slider = slider;
}
public void setTextField(JTextField field){
this.field = field;
}
}
Your JTextField reading works, but a problem is that you're first checking for the slider's value, and so if the slider if check is true, the method short circuits. To prove that it's working, move the slider all the way to the right, and then enter 1 or 2 into the JTextField.
If this were my project and I wanted to test this effect, I'd get all logic out of the painting method and instead allow my controllers to change a state value of the observed class, call repaint() and then draw the image based on that state.
For example, something like so:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
#SuppressWarnings("serial")
public class HangmanGUI2 extends JPanel {
private HangmanModel model = new HangmanModel();
private HangmanPanel2 panel2 = new HangmanPanel2(model);
private JSlider slider = new JSlider(0, HangmanModel.MAX_VALUE, 0);
private JTextField textField = new JTextField(10);
public HangmanGUI2() {
textField.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void removeUpdate(DocumentEvent e) {
updateModel(e);
}
#Override
public void insertUpdate(DocumentEvent e) {
updateModel(e);
}
#Override
public void changedUpdate(DocumentEvent e) {
updateModel(e);
}
private void updateModel(DocumentEvent e) {
Document doc = e.getDocument();
int length = doc.getLength();
try {
String text = doc.getText(0, length);
int value = Integer.parseInt(text.trim());
setModelValue(value);
} catch (BadLocationException e1) {
e1.printStackTrace();
} catch (NumberFormatException e1) {
// Do Nothing
}
}
});
slider.setMajorTickSpacing(1);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.addChangeListener(e -> {
int value = slider.getValue();
setModelValue(value);
});
setLayout(new BorderLayout());
add(panel2);
add(textField, BorderLayout.PAGE_START);
add(slider, BorderLayout.PAGE_END);
// new Timer(1000, e -> {
// model.increment();
// repaint();
// }).start();
}
protected void setModelValue(int value) {
model.setValue(value);
repaint();
}
private static void createAndShowGui() {
HangmanGUI2 mainPanel = new HangmanGUI2();
JFrame frame = new JFrame("HangmanGUI2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class HangmanModel {
public static final int MAX_VALUE = 9;
private int value = 0;
public int getValue() {
return value;
}
public void increment() {
setValue(getValue() + 1);
}
public void setValue(int value) {
this.value = Math.min(value, MAX_VALUE);
this.value = Math.max(this.value, 0);
}
}
#SuppressWarnings("serial")
class HangmanPanel2 extends JPanel {
private HangmanModel model;
private List<Image> images = ImageCreator.getImages();
public HangmanPanel2(HangmanModel model) {
this.model = model;
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || images.size() == 0) {
return super.getPreferredSize();
}
int w = images.get(0).getWidth(this);
int h = images.get(0).getHeight(this);
return new Dimension(w, h);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(images.get(model.getValue()), 0, 0, this);
}
}
class ImageCreator {
private static final int W = 284;
private static final int H = 425;
private static final Color BASE_COLOR = new Color(205, 133, 63);
public static List<Image> getImages() {
List<Image> images = new ArrayList<>();
BufferedImage img = new BufferedImage(W, H, BufferedImage.TYPE_INT_ARGB);
images.add(createImageCopy(img));
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(BASE_COLOR);
int xArc = W / 20;
int yArc = H - H / 5;
int arcWidth = W / 2;
int arcHeight = H / 5;
g2.fillArc(xArc, yArc, arcWidth, arcHeight, 0, 180);
images.add(createImageCopy(img));
// -----------------------------------------
g2.setColor(Color.BLACK);
int x1Line = xArc + arcWidth / 2;
int x2Line = x1Line;
int y1Line = yArc;
int y2Line = H / 6;
g2.drawLine(x1Line, y1Line, x2Line, y2Line);
images.add(createImageCopy(img));
// -----------------------------------------
int x3Line = x1Line;
int x4Line = x3Line + (W / 3) + 20;
int y3Line = y2Line;
int y4Line = y3Line;
g2.drawLine(x3Line, y3Line, x4Line, y4Line);
images.add(createImageCopy(img));
// -----------------------------------------
int x5Line = x4Line;
int x6Line = x5Line;
int y5Line = y4Line;
int y6Line = y5Line + W / 5; // + 60
g2.drawLine(x5Line, y5Line, x6Line, y6Line);
// -----------------------------------------
g2.setColor(new Color(255, 221, 204));
g2.fillOval(x6Line - H / 20, y6Line, H / 10,
H / 10); // -25, ...,50, 50
images.add(createImageCopy(img));
// -----------------------------------------
g2.setColor(Color.BLUE);
g2.fillOval((int) ((int) x6Line - H / 14.7),
(int) (y6Line + H / 10.41), (int) (H / 7.14),
(int) (H / 4.16)); // 34, 48, 70, 120
images.add(createImageCopy(img));
// -----------------------------------------
int x7Line = x6Line + (int) (H / 17.85); // 28
int x8Line = x7Line + (int) (H / 12.5); // 40
int y7Line = y6Line + (int) (H / 7.14); // 70
int y8Line = y7Line - (int) (H / 14.28); // 35
g2.setColor(Color.BLACK);
g2.drawLine(x7Line, y7Line, x8Line, y8Line);
images.add(createImageCopy(img));
// -----------------------------------------
int x9Line = x7Line - (int) (H / 9.43); // 53
int x10Line = x9Line - (int) (H / 14.28); // 35
int y9Line = y7Line;
int y10Line = y8Line;
g2.drawLine(x9Line, y9Line, x10Line, y10Line);
images.add(createImageCopy(img));
// -----------------------------------------
int x11Line = x7Line;
int x12Line = x8Line;
int y11Line = y7Line + (int) (H / 6.66); // 75
int y12Line = y8Line + (int) (H / 3.33); // 150
g2.drawLine(x11Line, y11Line, x12Line, y12Line);
images.add(createImageCopy(img));
// -----------------------------------------
int x13Line = x9Line;
int x14Line = x10Line;
int y13Line = y11Line;
int y14Line = y12Line;
g2.drawLine(x13Line, y13Line, x14Line, y14Line);
images.add(createImageCopy(img));
g2.dispose();
return images;
}
private static Image createImageCopy(BufferedImage img) {
int w = img.getWidth();
int h = img.getHeight();
BufferedImage img2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = img2.getGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
return img2;
}
}

Choosing a Layout Manager - Java

I'm having trouble to find the right Layout Manager. I have some images inside a JPanel, they are all different size so I wanted to use a Flow Layout to let the manager handle them. The manager fills all the first row as possible and then warps to another line. This is all ok, but what I want is to stop at second "warp". I just want to show 2 rows of images and if then you want to see more you must click a JButton to load the others. Actually the FlowLayout keeps inserting in a third line and the images are cutted by half because the panel is not "tall" enough. Any tips?
I've already tried with Flow Layout and Mig Layout without success.
Combine a FlowLayout(outerPanel) with a GridBagLayout(innerPannel)
u can define the rows by yourself, and then u put a JScrollPane over it so it wont cut your pictures and u will still be able to see them in full size(my suggestion)
I couldn't resist trying to solve this. I had hoped to make use of FlowLayouts, but in the end, I ended up using only GridBagLayouts: One for each row of images, plus one for the entire container. I may have over-engineered in terms of flexibility, but I imagine something like this may be useful to myself or others in the future.
In essence, every time the container changes size, or images are added/removed, or any of its visual properties change, updateLayout() is called, which rebuilds all of the GridBagLayout panels from scratch. I'm sure there are ways to make this more efficient, and I'm sure it's possible to write a LayoutManager2 implementation from scatch that does the job, but this performed reasonably well for me.
import java.util.List;
import java.util.ArrayList;
import java.util.Objects;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ImagePanel
extends JPanel {
private static final long serialVersionUID = 1;
/** #serial */
private final List<Icon> images = new ArrayList<>();
/** #serial */
private final List<Icon> scaledImages = new ArrayList<>();
/** #serial */
private int maxRowCount = 2;
/** #serial */
private int hgap = 6;
/** #serial */
private int vgap = 6;
/** #serial */
private int maxImageWidth = 200;
/** #serial */
private int maxImageHeight = 200;
public ImagePanel() {
setLayout(new GridBagLayout());
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent event) {
updateLayout();
}
});
}
#Override
public void addNotify() {
super.addNotify();
updateLayout();
}
#Override
public Dimension getPreferredSize() {
Rectangle screen = findGraphicsConfiguration().getBounds();
Dimension size = new Dimension();
Dimension row = new Dimension();
int rowsComputed = 0;
int gap = 0;
for (Icon image : scaledImages) {
if (row.width > 0 &&
row.width + gap + image.getIconWidth() > screen.width) {
if (++rowsComputed >= maxRowCount) {
break;
}
size.width = Math.max(size.width, row.width);
size.height += (size.height > 0 ? vgap : 0) + row.height;
row.setSize(0, 0);
gap = 0;
}
row.width += gap + image.getIconWidth();
row.height = Math.max(row.height, image.getIconHeight());
gap = hgap;
}
size.width = Math.max(size.width, row.width);
size.height += (size.height > 0 ? vgap : 0) + row.height;
return size;
}
private void updateLayout() {
int width = getWidth();
if (width == 0) {
return;
}
for (Component rowContainer : getComponents()) {
((JComponent) rowContainer).removeAll();
}
GridBagConstraints rowConstraints = new GridBagConstraints();
rowConstraints.gridwidth = GridBagConstraints.REMAINDER;
rowConstraints.weightx = 1;
rowConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
int row = -1;
int rowWidth = 0;
GridBagConstraints gbc = new GridBagConstraints();
for (Icon image : scaledImages) {
JComponent rowContainer = (row >= 0 && row < getComponentCount() ?
(JComponent) getComponent(row) : null);
int gap = (rowWidth > 0 ? hgap : 0);
if (rowContainer == null ||
rowWidth + gap + image.getIconWidth() > width) {
if (++row >= maxRowCount) {
break;
}
gap = 0;
rowWidth = 0;
if (row < getComponentCount()) {
rowContainer = (JComponent) getComponent(row);
} else {
rowContainer = new JPanel(new GridBagLayout());
add(rowContainer, rowConstraints);
}
rowConstraints.insets.top = vgap;
}
gbc.insets.left = gap;
JComponent imageContainer = new JLabel(image);
rowContainer.add(imageContainer, gbc);
rowWidth += gap + image.getIconWidth();
}
for (int i = getComponentCount() - 1; i >= maxRowCount; i--) {
remove(i);
}
}
private GraphicsConfiguration findGraphicsConfiguration() {
GraphicsConfiguration config = getGraphicsConfiguration();
if (config == null) {
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment();
config = env.getDefaultScreenDevice().getDefaultConfiguration();
}
return config;
}
private Icon scale(Icon image) {
int imageWidth = image.getIconWidth();
int imageHeight = image.getIconHeight();
if (imageWidth > maxImageWidth || imageHeight > maxImageHeight) {
float scale = Math.min((float) maxImageWidth / imageWidth,
(float) maxImageHeight / imageHeight);
if (scale < 1) {
GraphicsConfiguration config = findGraphicsConfiguration();
BufferedImage scaledImage = config.createCompatibleImage(
(int) (imageWidth * scale),
(int) (imageHeight * scale));
Graphics2D g = scaledImage.createGraphics();
g.scale(scale, scale);
image.paintIcon(this, g, 0, 0);
g.dispose();
image = new ImageIcon(scaledImage);
}
}
return image;
}
public List<Icon> getImages() {
return new ArrayList<>(images);
}
public void clearImages() {
images.clear();
updateLayout();
revalidate();
}
public void addImage(Icon image) {
Objects.requireNonNull(image, "Image cannot be null");
images.add(image);
scaledImages.add(scale(image));
updateLayout();
revalidate();
}
public void removeImage(Icon image) {
int index = images.indexOf(image);
if (index >= 0) {
removeImage(index);
}
}
public void removeImage(int index) {
images.remove(index);
scaledImages.remove(index);
updateLayout();
revalidate();
}
public int getHgap() {
return hgap;
}
public void setHgap(int gap) {
if (gap < 0) {
throw new IllegalArgumentException("Gap must be at least zero");
}
int old = this.hgap;
this.hgap = gap;
if (old != gap) {
updateLayout();
revalidate();
}
firePropertyChange("hgap", old, gap);
}
public int getVgap() {
return vgap;
}
public void setVgap(int gap) {
if (gap < 0) {
throw new IllegalArgumentException("Gap must be at least zero");
}
int old = this.vgap;
this.vgap = gap;
if (old != gap) {
updateLayout();
revalidate();
}
firePropertyChange("vgap", old, gap);
}
public int getMaxRowCount() {
return maxRowCount;
}
public void setMaxRowCount(int count) {
if (count < 0) {
throw new IllegalArgumentException("Count must be at least zero");
}
int old = this.maxRowCount;
this.maxRowCount = count;
if (old != count) {
updateLayout();
revalidate();
}
firePropertyChange("maxRowCount", old, count);
}
public int getMaxImageWidth() {
return maxImageWidth;
}
private void recomputeScaledImages() {
scaledImages.clear();
for (Icon image : images) {
scaledImages.add(scale(image));
}
}
public void setMaxImageWidth(int width) {
if (width <= 0) {
throw new IllegalArgumentException("Width must be positive");
}
int old = this.maxImageWidth;
this.maxImageWidth = width;
if (old != width) {
recomputeScaledImages();
updateLayout();
revalidate();
}
firePropertyChange("maxImageWidth", old, width);
}
public int getMaxImageHeight() {
return maxImageHeight;
}
public void setMaxImageHeight(int height) {
if (height <= 0) {
throw new IllegalArgumentException("Height must be positive");
}
int old = this.maxImageHeight;
this.maxImageHeight = height;
if (old != height) {
recomputeScaledImages();
updateLayout();
revalidate();
}
firePropertyChange("maxImageHeight", old, height);
}
public static void main(final String[] args)
throws java.io.IOException {
if (args.length == 0) {
System.err.println("Usage: java " + ImagePanel.class.getName()
+ " <directory> | <url1> <url2> ...");
System.exit(2);
}
final List<java.net.URL> urls;
if (args.length == 1 && !args[0].contains(":")) {
urls = new ArrayList<>();
try (java.nio.file.DirectoryStream<java.nio.file.Path> dir =
java.nio.file.Files.newDirectoryStream(
java.nio.file.Paths.get(args[0]))) {
for (java.nio.file.Path file : dir) {
urls.add(file.toUri().toURL());
}
}
} else {
urls = new ArrayList<>(args.length);
for (String url : args) {
urls.add(new java.net.URL(url));
}
}
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ImagePanel imagePanel = new ImagePanel();
for (java.net.URL url : urls) {
imagePanel.addImage(new ImageIcon(url));
}
javax.swing.JFrame frame =
new javax.swing.JFrame("ImagePanel");
frame.setDefaultCloseOperation(
javax.swing.JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.weightx = 1;
gbc.weighty = 1;
panel.add(imagePanel, gbc);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
}

how to move and scale image by dragging it's edges?

I have post this question before also but this time I have added only required and necessary code only although the code is somewhat lengthy.
I want to load image in Jlabel and then after change image when user clicks next button. And when user want to move or scale image he can just easily do it by selecting image edges but it's not working.
All problem are solved except the scaling and moving image.
my code :
public class CopyOfPictureEditor extends JFrame
{
private static final long serialVersionUID = 6676383931562999417L;
String[] validpicturetypes = {"png", "jpg", "jpeg", "gif"};
Stack<File> pictures ;
JLabel label = new JLabel();
BufferedImage a = null;
JPanel panel = new JPanel();
public CopyOfPictureEditor()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
e.printStackTrace();
}
JMenuBar menubar = new JMenuBar();
JMenu toolsmenu = new JMenu(" File ");
final File dir = new File("");
final JFileChooser file;
file = new JFileChooser();
file.setCurrentDirectory(dir);
file.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
file.showOpenDialog(panel);
String path = file.getSelectedFile().getAbsolutePath();
System.out.println(path);
pictures= getFilesInFolder(path.toString());
JButton NEXT = new JButton("");
NEXT.setToolTipText("Next Image");
Image imgn = null;
try
{
imgn = ImageIO.read(getClass().getResource("/images/next12.png"));
}catch (IOException e) {
e.printStackTrace();
}
NEXT.setIcon(new ImageIcon(imgn));
JPanel buttonPane = new JPanel();
buttonPane.add(Box.createRigidArea(new Dimension(250,0)));
buttonPane.add(Box.createRigidArea(new Dimension(250,0)));
NEXT.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
nextImage();
}
});
buttonPane.add(NEXT);
getContentPane().add(buttonPane, BorderLayout.SOUTH);
setJMenuBar(menubar);
menubar.add(toolsmenu);
panel.add(label,BorderLayout.CENTER);
add(panel);
setTitle("Aero Picture Editor");
setVisible(true);
setPreferredSize(getPreferredSize());
setLocation(0,0);
label.addMouseListenet(new MouseHandler());
label.addMouseMotionListenet(new MouseHandler());
}
public Stack<File> getFilesInFolder(String startPath){
File startFolder = new File(startPath);
Stack<File> picturestack = new Stack<File>();
String extension;
int dotindex;
for (File file : startFolder.listFiles()) {
extension = "";
dotindex = file.getName().lastIndexOf('.');
if (dotindex > 0) {
extension = file.getName().substring(dotindex + 1);
for (String filetype : validpicturetypes){
if (extension.equals(filetype)) {
picturestack.add(file);
}
}
}
}
return picturestack;
}
public void nextImage() {
String p;
File f;
try{
f= pictures.pop().getAbsoluteFile();
a=ImageIO.read(f);
p = f.getPath();
System.out.println(p);
} catch (IOException e1) {
e1.printStackTrace();
}
ImageIcon image = new ImageIcon(a);
label.setIcon(image);
repaint();
}
protected void paintComponent(Graphics g)
{
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - a.getWidth()) / 2;
int y = (getHeight() - a.getHeight()) / 2;
AffineTransform at = new AffineTransform();
at.translate(x, y);
g2d.setTransform(at);
g2d.drawImage(a, 0, 0, this);
g2d.dispose();
}
public enum MouseAction {
Move(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)),
ResizeSouth(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)),
ResizeNorth(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)),
ResizeEast(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)),
ResizeWest(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)),
ResizeNorthEast(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)),
ResizeNorthWest(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)),
ResizeSouthEast(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)),
ResizeSouthWest(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
private Cursor cursor;
private MouseAction(Cursor cursor) {
this.cursor = cursor;
}
public Cursor getCursor() {
return cursor;
}
}
public class MouseHandler extends MouseAdapter
{
private MouseAction action;
private Point clickPoint;
private boolean ignoreMoves;
protected void updateAction(MouseEvent e) {
int x = e.getX();
int y = e.getY();
int width = getWidth();
int height = getHeight();
if (x < 10 && y < 10) {
action = MouseAction.ResizeNorthWest;
} else if (x > width - 10 && y < 10) {
action = MouseAction.ResizeNorthWest;
} else if (y < 10) {
action = MouseAction.ResizeNorth;
} else if (x < 10 && y > height - 10) {
action = MouseAction.ResizeSouthWest;
} else if (x > width - 10 && y > height - 10) {
action = MouseAction.ResizeSouthEast;
} else if (y > height - 10) {
action = MouseAction.ResizeSouth;
} else if (x < 10) {
action = MouseAction.ResizeWest;
} else if (x > width - 10) {
action = MouseAction.ResizeEast;
} else {
action = MouseAction.Move;
} setCursor(action.getCursor());
}
#Override
public void mouseMoved(MouseEvent e) {
if (!ignoreMoves)
{
updateAction(e);
}
}
#Override
public void mousePressed(MouseEvent e) {
updateAction(e);
ignoreMoves = true;
clickPoint = e.getPoint();
repaint();
System.out.println(e.getX());
System.out.println(e.getY());*/
}
#Override
public void mouseReleased(MouseEvent e) {
clickPoint = null;
ignoreMoves = false;
}
#Override
public void mouseDragged(MouseEvent e) {
switch (action) {
case Move: {
Point p = e.getPoint();
p.x -= clickPoint.x;
p=SwingUtilities.convertPoint(label, p, null);
setLocation(p);
}
break;
case ResizeWest: {
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() - xDelta;
int x = getX() + xDelta;
setSize(width, getHeight());
setLocation(x, getY());
revalidate();
}
break;
case ResizeEast: {
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() + xDelta;
setSize(width, getHeight());
revalidate();
clickPoint = p;
}
break;
case ResizeNorth: {
Point p = e.getPoint();
int yDelta = p.y - clickPoint.y;
int height = getHeight() - yDelta;
int y = getY() + yDelta;
setSize(getWidth(), height);
setLocation(getX(), y);
revalidate();
}
break;
case ResizeSouth: {
Point p = e.getPoint();
int yDelta = p.y - clickPoint.y;
int height = getHeight() + yDelta;
setSize(getWidth(), height);
revalidate();
clickPoint = p;
}
break;
}
}
#Override
public void mouseExited(MouseEvent e)
{
}
}
}
Found this one:
label.addMouseListener(new MouseHandler());
label.addMouseMotionListener(new MouseHandler());
Since you set your clickPoint in mousePressed and want to have it in mouseDragged, it should be the same object. You should actually get some nullpointers in mouseDragged?
Hard to see without complete code, but for one, you're calling setSize and setLocation on the Window itself in your MouseDragged method. If you want to get the object the user clicked on you need to get it from e.getSource(), like:
public void mouseDragged(MouseEvent e){
JLabel l = (JLabel)e.getSource();
switch(action){
case ResizeWest:
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() - xDelta;
int x = getX() + xDelta;
l.setSize(width, getHeight()); // call setSize on JLabel l
l.setLocation(x, getY());
l.revalidate();
break;
}
Incidentally, why are you using a JLabel for this? I would use a Java object that draws itself onto the JFrame using the JFrame's graphics context.

Scrolling numbers java swing JTextField

Im wondering if anyone can help me replicate the below screenshot.
im tring to display a counter that will count in increments of 20 up to 100 the will count up 1 on the left hand side number then keep counting in increments and replicate..
eg:000 > 0/0/20 0/1/60
> 0/0/40 0/1/80
> 0/0/60 0/2/00
> 0/0/80 0/2/20
> 0/1/00 >>>>
> 0/1/20 0/9/80
> 0/1/40 1/0/00
etc...
This is an incredibly basic example. There is a lot of room for improvement in it's range checking.
The linear scroller is really simple. In the end I used the same basic concept as I did for the circular scroller, simply creating a BufferedImage with all the values marked on it, and based on the value, calculate the appropriate layout position.
The circular scroller took a little longer to bring about. The end result is really rather basic, the trouble is in calculating the under and overflow values.
The circular scroll simple creates a BufferedImage of all the available values. Based on it's display position, we either paint another copy of it before or after it, to give the illusion of flow...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.BoundedRangeModel;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class Altimiter {
public static void main(String[] args) {
new Altimiter();
}
public Altimiter() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private AltPane altPane;
public TestPane() {
JButton up = new JButton("+");
JButton down = new JButton("-");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(up, gbc);
gbc.gridy++;
add(down, gbc);
gbc.gridx++;
gbc.gridy = 0;
gbc.gridheight = GridBagConstraints.REMAINDER;
altPane = new AltPane();
add(altPane, gbc);
up.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
altPane.setSpeed(25);
}
});
down.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
altPane.setSpeed(-25);
}
});
altPane.setValue(0);
}
}
public class AltPane extends JPanel {
private LinearScrollerPane major;
private CircularScrollerPane minor;
private int altitude = 0;
private int direction = 0;
private Timer timer;
public AltPane() {
major = new LinearScrollerPane();
minor = new CircularScrollerPane();
major.setOpaque(false);
minor.setOpaque(false);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.VERTICAL;
gbc.weighty = 1;
add(major, gbc);
gbc.gridx++;
add(minor, gbc);
setBorder(new LineBorder(Color.BLUE));
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
altitude += direction;
if (altitude < 0) {
((Timer) e.getSource()).stop();
altitude = 0;
} else if (altitude > 20000) {
((Timer) e.getSource()).stop();
altitude = 20000;
}
System.out.println("value = " + altitude);
setValue(altitude);
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.setInitialDelay(0);
}
public void setSpeed(int speed) {
this.direction = speed;
timer.start();
}
public void setValue(int value) {
int hnds = value / 100;
int units = value - (hnds * 100);
if (units == 0) {
if (hnds > 0 && direction > 0) {
units = 100;
} else if (hnds > 0 && direction < 0) {
units = -1;
} else {
units = 0;
}
}
major.setValue(hnds);
minor.setValue(units);
invalidate();
repaint();
}
public int getValue() {
int ths = major.getValue();
int hnds = minor.getValue();
return (ths * 100) + hnds;
}
#Override
public void paint(Graphics g) {
super.paint(g);
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.top);
int height = getHeight() - (insets.top + insets.bottom);
g.setColor(new Color(255, 0, 0, 128));
int centerY = insets.top + (height / 2);
g.drawLine(insets.left, centerY, insets.left + width, centerY);
}
}
public class CircularScrollerPane extends JPanel {
private BufferedImage baseView;
private BoundedRangeModel model;
private float startValue = 0;
private float currentValue = 0;
private float targetValue = 0;
private int rowCount = 3;
private Timer timer;
private long startTime;
private int runTime = 1000;
public CircularScrollerPane() {
setModel(new DefaultBoundedRangeModel(0, 20, 0, 100));
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long diff = now - startTime;
if (diff >= runTime) {
((Timer) (e.getSource())).stop();
diff = runTime;
}
float progress = (float) diff / (float) runTime;
currentValue = calculateProgress(startValue, targetValue, progress);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(false);
}
public int getValue() {
return getModel().getValue();
}
public void setValue(int value) {
timer.stop();
BoundedRangeModel model = getModel();
if (value < model.getMinimum()) {
value = model.getMaximum() + (value + 1);
currentValue += model.getMaximum(); // overflow
} else if (value > model.getMaximum() - model.getExtent()) {
value = model.getMinimum() + (value - model.getMaximum());
currentValue -= model.getMaximum(); // underflow
}
startValue = currentValue;
targetValue = value;
model.setValue(value);
startTime = System.currentTimeMillis();
timer.start();
}
#Override
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(getFont());
return fm == null ? super.getPreferredSize() : new Dimension(fm.stringWidth("MMM"), fm.getHeight() * getRowCount());
}
public void setRowCount(int value) {
if (value != rowCount) {
int old = rowCount;
rowCount = value;
invalidate();
repaint();
firePropertyChange("rowCount", old, rowCount);
}
}
public int getRowCount() {
return rowCount;
}
public void setModel(BoundedRangeModel value) {
if (value != null) {
BoundedRangeModel old = model;
model = value;
if (model != null) {
currentValue = model.getValue();
targetValue = model.getValue();
} else {
currentValue = 0;
targetValue = 0;
}
baseView = null;
firePropertyChange("model", old, model);
}
}
public BoundedRangeModel getModel() {
return model;
}
#Override
public void invalidate() {
super.invalidate();
baseView = null;
}
public float getViewOffSet(float value) {
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
int rowHeight = fm.getHeight();
int extent = model.getExtent();
int min = model.getMinimum();
int max = model.getMaximum();
int viewRange = max - min;
int ticks = viewRange / extent;
float p = value / (float) viewRange;
return ((rowHeight * ticks) * p) + ((fm.getAscent() + fm.getDescent()) / 2);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage masterView = getMasterView();
if (masterView != null) {
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
int centerY = height / 2;
FontMetrics fm = g.getFontMetrics();
int yOffset = centerY - (int) getViewOffSet(currentValue);
g.drawImage(masterView, insets.left, insets.top + yOffset, this);
// Heading image...
if (yOffset > 0) {
g.drawImage(masterView, insets.left, insets.top + yOffset - masterView.getHeight(), this);
}
// Tailing image...
if (yOffset + masterView.getHeight() < height) {
g.drawImage(masterView, insets.left, insets.top + yOffset + masterView.getHeight(), this);
}
}
}
protected String pad(int value) {
StringBuilder sb = new StringBuilder(value);
sb.ensureCapacity(3);
sb.append(value);
while (sb.length() < 3) {
sb.insert(0, "0");
}
return sb.toString();
}
protected BufferedImage getMasterView() {
if (baseView == null) {
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
BoundedRangeModel model = getModel();
int extent = model.getExtent();
int min = model.getMinimum();
int max = model.getMaximum();
int viewRange = max - min;
int ticks = viewRange / extent;
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
baseView = new BufferedImage(width, fm.getHeight() * ticks, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = baseView.createGraphics();
g2d.setFont(font);
g2d.setColor(Color.BLACK);
int yPos = 0;
for (int index = min; index < max; index += extent) {
String value = pad(index);
g2d.drawString(value, width - fm.stringWidth(value), yPos + fm.getAscent());
yPos += fm.getHeight();
}
}
return baseView;
}
}
public class LinearScrollerPane extends JPanel {
private BufferedImage baseView;
private BoundedRangeModel model;
private float startValue = 0;
private float currentValue = 0;
private float targetValue = 0;
private int rowCount = 3;
private Timer timer;
private long startTime;
private int runTime = 1000;
public LinearScrollerPane() {
Font font = UIManager.getFont("Label.font");
setFont(font.deriveFont(Font.BOLD, font.getSize() + 4));
setModel(new DefaultBoundedRangeModel(0, 0, 0, 20));
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long now = System.currentTimeMillis();
long diff = now - startTime;
if (diff >= runTime) {
((Timer) (e.getSource())).stop();
diff = runTime;
}
float progress = (float) diff / (float) runTime;
currentValue = calculateProgress(startValue, targetValue, progress);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(false);
}
public int getValue() {
return getModel().getValue();
}
public void setValue(int value) {
timer.stop();
BoundedRangeModel model = getModel();
if (value < model.getMinimum()) {
value = model.getMinimum();
} else if (value > model.getMaximum() - model.getExtent()) {
value = model.getMaximum() - model.getExtent();
}
startValue = currentValue;
targetValue = value;
model.setValue(value);
startTime = System.currentTimeMillis();
timer.start();
}
#Override
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(getFont());
return fm == null ? super.getPreferredSize() : new Dimension(fm.stringWidth("MM"), fm.getHeight() * getRowCount());
}
public void setRowCount(int value) {
if (value != rowCount) {
int old = rowCount;
rowCount = value;
invalidate();
repaint();
firePropertyChange("rowCount", old, rowCount);
}
}
public int getRowCount() {
return rowCount;
}
public void setModel(BoundedRangeModel value) {
if (value != null) {
BoundedRangeModel old = model;
model = value;
if (model != null) {
currentValue = model.getValue();
targetValue = model.getValue();
} else {
currentValue = 0;
targetValue = 0;
}
baseView = null;
firePropertyChange("model", old, model);
}
}
public BoundedRangeModel getModel() {
return model;
}
#Override
public void invalidate() {
super.invalidate();
baseView = null;
}
public float getViewOffSet(float value) {
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
int rowHeight = fm.getHeight();
int min = model.getMinimum();
int max = model.getMaximum();
int viewRange = max - min;
int ticks = getTicks();
float p = value / (float) viewRange;
return ((rowHeight * ticks) * p) + ((fm.getAscent() + fm.getDescent()) / 2);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage masterView = getMasterView();
if (masterView != null) {
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
int centerY = height / 2;
FontMetrics fm = g.getFontMetrics();
int yOffset = centerY - (int) getViewOffSet(currentValue);
g.drawImage(masterView, insets.left, insets.top + yOffset, this);
}
}
protected String pad(int value) {
StringBuilder sb = new StringBuilder(value);
sb.ensureCapacity(3);
sb.append(value);
while (sb.length() < 3) {
sb.insert(0, "0");
}
return sb.toString();
}
protected int getTicks() {
BoundedRangeModel model = getModel();
int extent = model.getExtent();
int min = model.getMinimum();
int max = model.getMaximum();
int viewRange = max - min;
int ticks = viewRange;
if (extent > 0) {
ticks = viewRange / extent;
}
return ticks;
}
protected BufferedImage getMasterView() {
if (baseView == null) {
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
BoundedRangeModel model = getModel();
int extent = model.getExtent();
int min = model.getMinimum();
int max = model.getMaximum();
int ticks = getTicks() + 1;
Font font = getFont();
FontMetrics fm = getFontMetrics(font);
baseView = new BufferedImage(width, fm.getHeight() * ticks, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = baseView.createGraphics();
g2d.setFont(font);
g2d.setColor(Color.BLACK);
int yPos = 0;
for (int index = min; index < max + 1; index += Math.max(1, extent)) {
String value = String.valueOf(index);
g2d.drawString(value, width - fm.stringWidth(value), yPos + fm.getAscent());
yPos += fm.getHeight();
}
g2d.dispose();
}
return baseView;
}
}
public static float calculateProgress(float startValue, float endValue, double fraction) {
float value = 0;
float distance = endValue - startValue;
value = (float) (distance * fraction);
value += startValue;
return value;
}
}
You can do this with a custom SliderUI, shown here, is a JSlider having a VERTICAL orientation. The example calls drawLine () in paintThumb(), but you can use TextLayout, illustrated here, to render the numbers.

swing layout: vertical flow

What LayoutManager should I use to achieve a transposed version of FlowLayout?
Essentially, I want a vertical list which occupies multiple columns if it can't fit all of it's components within one column.
+------------------------+
| item 1 |
| item 2 |
| item 3 |
| item 4 |
| item 5 |
| item 6 |
| item 7 |
| item 8 |
+------------------------+
or
+------------------------+
| item 1 item 7 |
| item 2 item 8 |
| item 3 |
| item 4 |
| item 5 |
| item 6 |
+------------------------+
this wrapping logic needs to happen dynamically, ie as the container is resized.
very easy,you just need this.
yourPanel.setLayout(new BoxLayout(yourPanel, BoxLayout.Y_AXIS));
after this,you just add view to yourPanel and you will get vertical flow layout.
I'm working on a solution to my own question (very similar: I need to flow vertically but constrain width horizontally), I got a quick example sort of working and maybe it gets you started with a custom layout manager:
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager2;
import java.util.Random;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import com.google.common.collect.Sets;
public class VerticalFlowLayout implements LayoutManager2
{
final private Set<Component> components = Sets.newLinkedHashSet();
private int hgap = 0;
private int vgap = 0;
public void setHGap(int hgap) { this.hgap = hgap; }
public void setVGap(int vgap) { this.vgap = vgap; }
#Override public void addLayoutComponent(Component comp, Object constraints) {
this.components.add(comp);
}
/* these 3 methods need to be overridden properly */
#Override public float getLayoutAlignmentX(Container target) {
// TODO Auto-generated method stub
return 0;
}
#Override public float getLayoutAlignmentY(Container target) {
// TODO Auto-generated method stub
return 0;
}
#Override public void invalidateLayout(Container target) {
// TODO Auto-generated method stub
}
#Override public void addLayoutComponent(String name, Component comp) {
this.components.add(comp);
}
#Override public void layoutContainer(Container parent) {
int x = 0;
int y = 0;
int columnWidth = 0;
for (Component c : this.components)
{
if (c.isVisible())
{
Dimension d = c.getPreferredSize();
columnWidth = Math.max(columnWidth, d.width);
if (y+d.height > parent.getHeight())
{
x += columnWidth + this.hgap;
y = 0;
}
c.setBounds(x, y, d.width, d.height);
y += d.height + this.vgap;
}
}
}
/* these 3 methods need to be overridden properly */
#Override public Dimension minimumLayoutSize(Container parent) {
return new Dimension(0,0);
}
#Override public Dimension preferredLayoutSize(Container parent) {
return new Dimension(200,200);
}
#Override public Dimension maximumLayoutSize(Container target) {
return new Dimension(600,600);
}
#Override public void removeLayoutComponent(Component comp) {
this.components.remove(comp);
}
public static void main(String[] args) {
JFrame frame = new JFrame("VerticalFlowLayoutTest");
VerticalFlowLayout vfl = new VerticalFlowLayout();
JPanel panel = new JPanel(vfl);
vfl.setHGap(20);
vfl.setVGap(2);
int n = 19;
Random r = new Random(12345);
for (int i = 0; i < n; ++i)
{
JLabel label = new JLabel(labelName(i,r));
panel.add(label);
}
frame.setContentPane(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static String labelName(int i, Random r) {
StringBuilder sb = new StringBuilder();
sb.append("label #");
sb.append(i);
sb.append(" ");
int n = r.nextInt(26);
for (int j = 0; j < n; ++j)
sb.append("_");
return sb.toString();
}
}
I modified the GridLayout to layout components by column first instead of by row:
http://forums.oracle.com/forums/thread.jspa?messageID=5716765#5716765
Either you'll need a custom layout manager or you can use something like a GridBagLayout and control yourself.
An example:
Component parent = ...;
GridBagConstraints c = ...;
//set other parameters
c.gridx = 0;
c.gridy = 0;
parent.add([component1], c);
c.gridy++;
parent.add([component2], c);
c.gridy++;
This post is quite old :)
Codes in below link does not work fine, (calculate the height of invisible items which it is wrong!)
http://www.java2s.com/Code/Java/Swing-JFC/AverticallayoutmanagersimilartojavaawtFlowLayout.htm
I changed some parts so it works fine now.
I also clean up insets so, if you need it, please add it yourself.
thanks
package Common;
/**
* #author Pasban
*/
import java.awt.*;
import java.util.*;
public class VerticalLayout implements LayoutManager {
public final static int CENTER = 0;
public final static int RIGHT = 1;
public final static int LEFT = 2;
public final static int BOTH = 3;
public final static int TOP = 1;
public final static int BOTTOM = 2;
private int vgap;
private int alignment;
private int anchor;
private Hashtable comps;
public VerticalLayout() {
this(5, CENTER, TOP);
}
public VerticalLayout(int vgap) {
this(vgap, CENTER, TOP);
}
public VerticalLayout(int vgap, int alignment) {
this(vgap, alignment, TOP);
}
public VerticalLayout(int vgap, int alignment, int anchor) {
this.vgap = vgap;
this.alignment = alignment;
this.anchor = anchor;
}
private Dimension layoutSize(Container parent, boolean minimum) {
Dimension dim = new Dimension(0, 0);
Dimension d;
synchronized (parent.getTreeLock()) {
int n = parent.getComponentCount();
for (int i = 0; i < n; i++) {
Component c = parent.getComponent(i);
if (c.isVisible()) {
d = minimum ? c.getMinimumSize() : c.getPreferredSize();
dim.width = Math.max(dim.width, d.width);
dim.height += d.height;
if (i > 0) {
dim.height += vgap;
}
}
}
}
Insets insets = parent.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom + vgap + vgap;
return dim;
}
public void layoutContainer(Container parent) {
Insets insets = parent.getInsets();
synchronized (parent.getTreeLock()) {
int n = parent.getComponentCount();
Dimension pd = parent.getSize();
int y = 0;
for (int i = 0; i < n; i++) {
Component c = parent.getComponent(i);
Dimension d = c.getPreferredSize();
if (c.isVisible()) {
y += d.height + vgap;
}
}
y -= vgap;
if (anchor == TOP) {
y = insets.top;
} else if (anchor == CENTER) {
y = (pd.height - y) / 2;
} else {
y = pd.height - y - insets.bottom;
}
for (int i = 0; i < n; i++) {
Component c = parent.getComponent(i);
Dimension d = c.getPreferredSize();
if (!c.isVisible()) {
continue;
}
int x = 1;
int wid = pd.width - 3;
c.setBounds(x, y, wid, d.height);
y += d.height + vgap;
}
}
}
public Dimension minimumLayoutSize(Container parent) {
return layoutSize(parent, false);
}
public Dimension preferredLayoutSize(Container parent) {
return layoutSize(parent, false);
}
public void addLayoutComponent(String name, Component comp) {
}
public void removeLayoutComponent(Component comp) {
}
public String toString() {
return getClass().getName() + "[vgap=" + vgap + " align=" + alignment + " anchor=" + anchor + "]";
}
}
The solution of Jason S works for me.
The only issue I corrected is I don't have com.google.common.collect.Sets or java.collections.LinkedHashSet libs (Java 7)...
so I just replace
final private Set<Component> components = Sets.newLinkedHashSet();
by
final private List<Component> components = new LinkedList<>();
and all seems to be ok :)

Categories

Resources