I'm using GridBagLayout to make a StatusBar which looks like in the picture. I have 4 areas, so I have a button in the first one, then info messages in the second one, and then I want two more (and i also have a fifth one to make the corner).
The button area fits perfectly, because the content is always a button with the same width. Same with the corner area. The info area must get all the space available. 3rd and 4th areas must have a fixed value, independent from the screen size.
How can I do that?
My current code is:
public MyStatusBar() {
setLayout(new GridBagLayout());
setPreferredSize(new Dimension(getWidth(), 23));
GridBagConstraints c = new GridBagConstraints();
botonDispositivo = new JButton("");
this.setText(0, "Disconnected");
URL imageUrl = getClass().getResource("resources/22x22/dispositivo01.png");
this.setButtonImg(imageUrl);
this.setButtonEnabled(false);
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.WEST;
c.gridwidth = 1;
c.gridheight = 1;
this.add(botonDispositivo, c);
c.insets= new Insets(0,10,0,0);
c.gridx ++;
c.gridy = 0;
c.weightx = 0.7;
c.fill = GridBagConstraints.HORIZONTAL;
msgLabel = new JLabel("");
msgLabel.setPreferredSize(new Dimension(500, msgLabel.getHeight()));
this.add(msgLabel, c);
this.setText(1, "Waiting for potentiostat conection");
c.gridx ++;
c.gridy = 0;
c.weightx = 0.0;
c.fill = GridBagConstraints.NONE;
this.add(new SeparatorPanel(Color.GRAY, Color.WHITE), c);
c.gridx ++;
c.gridy = 0;
c.fill = GridBagConstraints.NONE;
c.weightx = 0.0;
overErrorLabel = new JLabel("");
overErrorLabel.setSize(new Dimension(150, overErrorLabel.getHeight()));
this.add(overErrorLabel, c);
//this.setText(2, "");
c.gridx ++;
c.gridy = 0;
c.weightx = 0.0;
c.fill = GridBagConstraints.NONE;
this.add(new SeparatorPanel(Color.GRAY, Color.WHITE), c);
c.gridx ++;
c.gridy = 0;
c.weightx = 0.0;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.EAST;
timeLabel = new JLabel("");
timeLabel.setMinimumSize(new Dimension(150, timeLabel.getHeight()));
//timeLabel.setMaximumSize(new Dimension(150, timeLabel.getHeight()));
this.add(timeLabel, c);
//this.setText(3, "");
JPanel rightPanel = new JPanel(new GridBagLayout());
c.gridx ++;
c.gridy = 0;
c.weightx = 0.0;
c.fill = GridBagConstraints.BOTH;
rightPanel.add(new JLabel(new AngledLinesWindowsCornerIcon()), c);
rightPanel.setOpaque(false);
c.gridx ++;
c.grid开发者_运维百科y = 0;
c.fill = GridBagConstraints.BOTH;
this.add(rightPanel, c);
setBackground(SystemColor.control);
}
You set preferred, minimum, maximul etc. size for different labels. I think all you need is set weight X>0 and fill param=HORIZONTAL of the constraint for the label you want to be resized and weightX=0 and fill-NONE for the labels you don't want to be resized.
Also use ipadx to specify min size for labels.
for better and easiest output to the GUI is better look for Borderlayout
,
JPanel#setPrefferedSize(200, 30);
for JButton
with Icon
and JLabel put to the WEST area
JPanel#setPrefferedSize(200, 30);
(rightPanel) to the EAST area
put another JPanel
to CENTER area
If you want a cell inside a GridBagLayout to be fixed in width (or height), then there is a working solution for this. Say you want cell at (x,y) to be fixed in width but the JLabel inside it has variable content, that must be changed during runtime. Using a GridBagLayout would then relocate other components if the JLabel needs to change size, thus forcing the containing cell to be resized. To counter this you can do one of the following:
- You can add an extra row (y + 1) to the layout in which the xth cell contains a dummy JPanel, and on that JPanel you call
.setPreferredSize(new Dimension(desiredWidth, 0));
. - The same, but instead of setting the preferredSize you set the insets on the GridBagConstraints object used while adding this dummy panel. So if you want a fixed width, just do
gbc.insets = new Insets(0,preferredWidth,0,0);
orgbc.insets = new Insets(0,0,0,preferredWidth);
. This way the panel itself is (0,0) in dimension but the containing cell will be forced to be as wide as you specify (because the insets are the external padding, seen from the component).
The first one requires you to call setPreferredSize() and this always makes me feel uncomfortable, because you are messing with the task of the LayoutManager. Therefore I prefer the latter solution but you will not be able to visualize your cell as your dummy panel has no size. In the former solution you can make your cell visible by giving the panel a background color.
The benefits of this approach is that you don't have to bother about setting sizes on your JLabel, especially its height which is unknown before it is displayed. You can't set a preferredSize on the JLabel because you don't know which height it must have (platform dependent, font dependent etc.). You just add it, and using the dummy row with the dummy panel will force the cell containing the JLabel to be as wide as desiredWidth
.
This solution works given that the JLabel's width will not exceed desiredWidth
, because in that case the cell will also grow. You can always put a maximumSize on the JLabel to solve this (here you don't have the problem of unknown heights - for maximum height you can use Integer.MAX_VALUE).
The same story goes for height, just introduce a dummy column and add a dummy JPanel with dimension = (0, preferredHeight) in the cell at the row where the problem occurs.
Downside of this approach: you have to use dummy components which is never the best way to go, but it works quite well here.
精彩评论