Fixed widths into a GridBagLayout
Asked Answered
C

3

5

enter image description here

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.gridy = 0;
        c.fill = GridBagConstraints.BOTH;
        this.add(rightPanel, c);

        setBackground(SystemColor.control);
      }
Coimbra answered 27/7, 2011 at 10:3 Comment(0)
E
4

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

Evaporite answered 27/7, 2011 at 10:24 Comment(0)
J
12

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.

Jolo answered 27/7, 2011 at 10:19 Comment(6)
Looks OK, but there is a problem:Coimbra
when the labels are empty, the ipadx is the area width. But when I write into the label and it gets for example 100px wide, the area gets 100px+ipadx wide. I want it to stay ipadx wide always, how shall I do that?Coimbra
From javadoc:ipadx This field specifies the internal padding of the component, how much space to add to the minimum width of the component. The width of the component is at least its minimum width plus ipadx pixels. SO it depends on min size of you content.Jolo
Yeah, I already know why it's behaving like that, what I want it to have a fixed width independently from the label width (which always will be smaller). When label width=0 your solution is OK, but when something is written, the described problem appears. Is there any way of changing the ipadx value to "constant_value-label.getWidth()" on the fly?Coimbra
May be it's better to specify min/max/pref size of the label and don't use the label at all? Or just override the getMinimumSize() of the label to return always 0Jolo
OK, I have tried the overrride and sets Width to 0 too, so the label gets invisible. I need another solutionCoimbra
E
4

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

Evaporite answered 27/7, 2011 at 10:24 Comment(0)
I
3

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); or gbc.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.

Inform answered 4/3, 2013 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.