This is my code:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame();
JPanel jp = new JPanel();
jp.setMinimumSize(new Dimension(200, 200));
jp.setPreferredSize(new Dimension(200, 200));
//frame.getContentPane().setMinimumSize(new Dimension(200, 200));
//frame.getContentPane().setPreferredSize(new Dimension(200, 200));
frame.getContentPane().add(jp);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
It behaves exactly the way I want. User can resize the JFrame
but it'll always be large enough to hold 200px x 200px JPanel
. But when I remove:
JFrame.setDefaultLookAndFeelDecorated(true);
user can resize JFrame
to any size.
Why does default look and feel decoration affect resizing? How can i make it work without setDefaultLookAndFeelDecorated(true)
? I know I can set frames minimum size manually (JFrame#setMinimumSize(new Dimension dim)
) and I will if there is no smarter solution.
I'm using jdk 1.7 on Windows 7.
This use to be a bug, the page speaks of work arounds like:
setSize()
and check if the new size is less than the desiredpaint(Graphics g)
of JFrame
check height and width and "re-create" frame to new minimum sizehowever a person claims it to be fixed as the original example issued for the bug proposal omitted the call to setMinimumSize(...)
, this is needed because JFrame does not enforce minimum size
Here is the snippet which shows that persons' code:
import java.awt.Dimension;
import javax.swing.*;
public class JavaApplication118 {
private final Dimension m_dim = new Dimension(200, 150);
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JavaApplication118().createAndShowUI();
}
});
}
private void createAndShowUI() {
// JFrame.setDefaultLookAndFeelDecorated(true);
final JFrame frame = new JFrame("Test") {
@Override
public Dimension getMinimumSize() {
return m_dim;
}
};
frame.setMinimumSize(m_dim);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
// frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(JFrame frame) {
JPanel jp = new JPanel();
jp.setMinimumSize(new Dimension(200, 200));
jp.setPreferredSize(new Dimension(400, 400));//for testing
frame.getContentPane().add(jp);
}
}
EDIT
The snippet overrode getMinimumSize()
though this seems redundant after calling setMinimumSize(..)
, I kept it included as that's how I found the snippet (I did remove the overridden getPreferredSize()
method of the JFrame
which the snippet included).
Why does default look and feel decoration affect resizing?
Because then the window sizing is under the complete control of the LAF while dragging: The mouseHandler installed by (f.i.) MetalRootPaneUI doesn't resize the window below the min returned by the LayoutManager. Without setting the frame's minimumSize, you can still decrease its size programatically.
The only way (unfortunately) to enforce a window's minimum size always is to manually set it. Unfortunate, as that implies keeping track of dynamic changes of that minimum and update it as appropriate.
A snippet to play with (un/comment the defaultDecoration and frame min setting)
JFrame.setDefaultLookAndFeelDecorated(true);
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
Dimension m = getMinimumSize();
// visualize the min
g.drawRect(0, 0, m.width - 1, m.height -1);
}
};
// BEWARE: for demonstration only, NEVER do in production code
panel.setMinimumSize(new Dimension(400, 400));
panel.setPreferredSize(panel.getMinimumSize());
final JXFrame frame = new JXFrame("", true);
Action action = new AbstractAction("resize") {
@Override
public void actionPerformed(ActionEvent e) {
frame.setSize(300, 300);
LOG.info("succeeded? " + frame.getSize());
}
};
panel.add(new JButton(action));
frame.add(panel);
frame.pack();
// set minimum is required to enforce the minimum
frame.setMinimumSize(frame.getMinimumSize());
Update
Looking at the Window source, turns out that you can have auto-magic dynamic respect of min size by overriding isMinimumSizeSet and returning true uncondinionally:
final JXFrame frame = new JXFrame("", true) {
@Override
public boolean isMinimumSizeSet() {
return true;
}
};
...
// no longer needed
// frame.setMinimumSize(frame.getMinimumSize());
not tested for side-effects, though
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With