How to lay out components so that the middle component gets all the space, but the rightmost component is aligned to the left?

I have a panel consisting of a button (X), a label (Y), and a progress bar (Z). Ideally, I would like to lay them out like this:

| XX Y---------------Y Z---Z ============= | <-- expanded-size panel ^ extra space | XX Y------Y Z---Z | <-- reduced-size panel 

The above diagram shows:

  • When the panel expands, the extra space must go to the label (Y) so that the label fully displays its text.
  • The progress bar (Z) should always stay next to the mark (Y).
  • When the panel is reduced, the label size (Y) should be reduced.
  • The button (X) and the dimensions of the progress bar (Z) should be constant, not the label (Y).

However, when I try to use GroupLayout, this happens when the panel expands:

 | XX Y---------------Y ============= Z---Z | <-- expanded-size panel (bad) 

The problem is that when the panel has extra space, the shortcut (Y) expands beyond what it needs, which pushes the progress bar (Z) to the right. I would prefer the position of the progress bar (Z) to be next to the label (Y).

How can I execute this layout?

Sample code ("Blah.java"):

 import java.awt.*; import javax.swing.*; public class Blah extends JPanel { public Blah() { final JButton X = new JButton("X"); final JLabel Y = new JLabel("yyyyyyyyyyy"); Y.setOpaque(true); Y.setBackground(Color.YELLOW); final JProgressBar Z = new JProgressBar(); Z.setIndeterminate(true); final GroupLayout l = new GroupLayout(this); super.setLayout(l); l.setHorizontalGroup( l.createSequentialGroup() .addComponent(X, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addComponent(Y, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(Z, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); l.setVerticalGroup( l.createParallelGroup() .addComponent(X) .addComponent(Y) .addComponent(Z)); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { final JFrame frame = new JFrame("Blah"); frame.add(new Blah()); frame.pack(); frame.setVisible(true); } }); } } 
+4
source share
2 answers

After hitting my head against the wall for too long, I found this little pearl of documentation in the SpringLayout tutorial ( http://docs.oracle.com/javase/tutorial/uiswing/layout/spring.html ):

When the methods of the getMaximumSize and getPreferredSize return the same value, SpringLayout interprets this as meaning that the component should not be stretched.

Thus, with SpringLayout and in manual mode, the maximum size of Y and Z can be reached the ideal plan described above. Here is the code:

 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Blah extends JPanel { public Blah() { final JButton X = new JButton("X"); final JLabel Y = new JLabel("yyyyyyyyyyy"); Y.setOpaque(true); Y.setBackground(Color.YELLOW); final JProgressBar Z = new JProgressBar(); Z.setIndeterminate(true); final SpringLayout l = new SpringLayout(); super.setLayout(l); super.add(X); super.add(Y); super.add(Z); Z.setMaximumSize(Z.getPreferredSize()); l.putConstraint(SpringLayout.WEST, X, 10, SpringLayout.WEST, this); l.putConstraint(SpringLayout.WEST, Y, 10, SpringLayout.EAST, X); l.putConstraint(SpringLayout.WEST, Z, 10, SpringLayout.EAST, Y); l.putConstraint(SpringLayout.EAST, this, 10, SpringLayout.EAST, Z); l.putConstraint(SpringLayout.NORTH, X, 10, SpringLayout.NORTH, this); l.putConstraint(SpringLayout.NORTH, Y, 10, SpringLayout.NORTH, this); l.putConstraint(SpringLayout.NORTH, Z, 10, SpringLayout.NORTH, this); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { final JFrame frame = new JFrame("Blah"); frame.add(new Blah()); frame.pack(); frame.setVisible(true); } }); } } 
0
source

Very rarely, one layout manager meets all your needs. Instead, you can use the compound layout approach.

That is, separate each individual layout requirement into a separate component with its own layout manager. Then they added all this to their main component, managing the general requirements.

As an example

enter image description hereenter image description here

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.border.LineBorder; public class SimpleGridBagLayout { public static void main(String[] args) { new SimpleGridBagLayout(); } public SimpleGridBagLayout() { 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 { public TestPane() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; add(createLabel("XXX-XXX", Color.BLUE), gbc); JPanel panel = new JPanel(); panel.add(createLabel("YY", Color.RED)); panel.add(createLabel("ZZZZZ---ZZZZZ", Color.GREEN), gbc); gbc.gridx++; gbc.weightx = 1; add(panel, gbc); } protected JLabel createLabel(String text, Color border) { JLabel label = new JLabel(text); label.setBorder(new LineBorder(border)); return label; } @Override public Dimension getPreferredSize() { return new Dimension(200, 100); } } } 

There are a number of factors. The preferred and minimum sizes of child components will significantly affect how some layout managers place components there when the available size is small.

Update

 public TestPane() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; add(createLabel("XXX-XXX", Color.BLUE), gbc); JPanel panel = new JPanel(new GridBagLayout()); gbc = new GridBagConstraints(); gbc.gridx = 0; panel.add(createLabel("YY", Color.RED), gbc); gbc.gridx = 1; panel.add(createLabel("ZZZZZ---ZZZZZ", Color.GREEN), gbc); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.weightx = 1; add(panel, gbc); } 

Update

Now with a progress bar "not contracting"

 public class TestPane extends JPanel { public TestPane() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; add(createLabel("XXX-XXX", Color.BLUE), gbc); JPanel panel = new JPanel(new GridBagLayout()); gbc = new GridBagConstraints(); gbc.gridx = 0; panel.add(createLabel("YY", Color.RED), gbc); gbc.gridx = 1; MyProgressBar pb = new MyProgressBar(); panel.add(pb, gbc); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.weightx = 1; add(panel, gbc); } protected JLabel createLabel(String text, Color border) { JLabel label = new JLabel(text); label.setBorder(new LineBorder(border)); return label; } @Override public Dimension getPreferredSize() { return new Dimension(200, 100); } } public class MyProgressBar extends JProgressBar { @Override public Dimension getPreferredSize() { Dimension ps = super.getPreferredSize(); ps.width = 75; return ps; } @Override public Dimension getMinimumSize() { return getPreferredSize(); } } 
+4
source

Source: https://habr.com/ru/post/1490395/


All Articles