4

I am testing out MigLayout for a project, and I can't seem to figure out the MigLayout way of controlling the size of the whole panel which is being layed out. I am adapting the example in the MigLayout whitepaper. Also, I am writing in Python and using Jython rather than writing in Java. That said, here is my current code.

layout = MigLayout("fillx",
                   # Column constraints
                   "[right]rel[grow,fill]",
                   # Row constraints
                   "[]10[]10[]")
panel = JPanel(layout)

panel.add(JLabel("Enter size:"),
          "")
panel.add(JTextField(""),
          "wrap, width 150:250")
panel.add(JLabel("Enter weight:"),
          "")
panel.add(JTextField(""),
          "wrap, width 150:250")
panel.add(JButton("Ok"),
          "span 2, align center, width 100:150")

The panel then goes into a JFrame for display. When I resize the frame, the controls resize nicely and obey their minimum sizes. However, there is no minimum size on the frame, nor does there seem to be any way to get to the real minimum size of the panel to set it for the frame. Asking for the panel's minimum size returns a size which, when set on the frame (plus insets), cuts off the button and half of the text fields.

What I want is to be able to set the minimum size for the frame (not hard-coded!) so that the panel fits and none of its controls are cut off. What is the best way to do this?

Instance Hunter
  • 7,621
  • 5
  • 39
  • 52

3 Answers3

2

How about the pack method ???

Update:

Now I understand what you are trying to do. I am sorry to disappoint you but 90% of standalone applications are written with

  1. Dialog windows that have a fixed size (non-resizable) and a perfectly tuned to content

  2. Main Windows that are resizable but have a minimum size (e.g. 800x600)

What you want (a resizable window with no hard-coded values) is possible but very difficult to achieve (this is the other 10% of applications)

Since Java Swing has notorious difficulties with layout (this is the main reason of the existance of so many Layout managers) I suggest you follow the easy way.

You can play with the setPrefferedSize and setMinimum size methods of various component but it will be hard to get it perfect.

kazanaki
  • 7,644
  • 8
  • 49
  • 75
2

Personally, I wouldn't stress too much about the minimum size as long as the preferred size (what you get after pack() is appropriate. If for some reason the user wants to reduce the window down to a size where the components in it get clipped, then let them. Maybe they just want to get the bottom of your window out the way so they can see what remains and something else on their monitor at the same time.

I would argue that the true minimum size of any window is the sum of it's border and title bar and room for a few characters of the title text and an ellipsis. If the user want something smaller than what will allow all the components to show unclipped who are you to enforce otherwise?

Using any of the several table-based layout managers available on the web, like MIG Layout, you should be able to easily get the resizing behavior you want.

Shameless self plug: If you find MIG Layout hard to use, my MatrixLayout is, I think, easier to use. But MIG layout is more powerful. I deliberately chose to code MatrixLayout to not inhibit panels from reducing below their calculated minimum size.

Lawrence Dol
  • 59,198
  • 25
  • 134
  • 183
  • @SM: Off topic: Where have you been Software Monkey? I haven't see you around for a while. Is nice to see you again. Bye bye! – OscarRyz Aug 27 '09 at 04:58
  • @Oscar: I've been around, checking SO a couple times a week, throwing out and answer here and there where I think I can help. But mostly, I'm putting in long hours on a product deadline - the usual: X amount of work and X/10 time to do it. – Lawrence Dol Aug 27 '09 at 05:09
0

I just figured out how to refresh the frame size according to the sum of size of all the contained components without hardcoding anything.

  1. Create a JPanel panel as your working panel, instead of touching the contentPane. Just add it back to the contentPane. Don't touch the contentPane, it is the key.

  2. Set the layout of panel without hardcoded row height, column width, etc. This may ruin the layout, because your hardcoded height may be lesser or more of it is needed, leaving some line with wrong size, and leave your last line/column half cut off.

  3. Add your elements into panel. When adding them you can specify sizes.

  4. Add panel back to contentPane: getContentPane().add(panel); We don't need to set the layout of contentPane.

  5. At last, pack(), setVisible(true) as you wish. No need to setSize(), setBounds(), etc. The insets and gaps will be handled automatically by MigLayout. Viola!

A SCCEE:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import net.miginfocom.swing.MigLayout;

public class InsetsAndBorder extends JFrame {
    public InsetsAndBorder() {
        begin();
    }

    private void begin() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        panel.setLayout(new MigLayout("insets 2 2 2 2, fillx, debug", "3[]3[]3[]3", "5[]5[]5[]5"));

        JLabel label1 = new JLabel("1");
        JLabel label2 = new JLabel("2");

        JButton button = new JButton("No way!");

        panel.add(label1, "cell 1 2, grow");

        panel.add(label2, "cell 2 2, grow");

        panel.add(button, "cell 0 1, grow");

        getContentPane().add(panel);
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                InsetsAndBorder frame = new InsetsAndBorder();

            }

        });
    }
}
WesternGun
  • 7,222
  • 56
  • 97