0

I am using Java 8 and I have a JFrame which I want to have minimum size required. It is okay if the frame is enlarged, but it should not go below minimum so that the GUI is usable. For this I use the solution described in this answer. I first use pack then set minimum size as frame size. But for some reason it only works if Windows scaling is set to 1/100%. For other scaling values I can actually make the frame smaller by dragging(this is proportional to the scaling value).

Here's an example code

import java.awt.BorderLayout;
import javax.swing.*;

public class ScalingProblem extends JFrame {

  public ScalingProblem() {

    setTitle("My Gui");
    setSize(400, 400);

    JButton button = new JButton("Button 1");
    JButton button2 = new JButton("Button 2");
    JButton button3 = new JButton("Button 3");
    JButton button4 = new JButton("Button 4");
    JPanel panel = new JPanel(new BorderLayout());

    panel.add(button, BorderLayout.NORTH);
    panel.add(button2, BorderLayout.EAST);
    panel.add(button3, BorderLayout.WEST);
    panel.add(button4, BorderLayout.SOUTH);

    this.getContentPane().add(panel);

    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    pack();
    setMinimumSize(getSize());
  }

  public static void main(String[] args) {

    ScalingProblem a = new ScalingProblem();
  }
}

Even after setting minimum size of frame I can make it smaller by a factor of 1.25 which is also my scaling factor for display.

So basically when dragging the frame, size can be made smaller then the minimum size set using setMinimumSize. I tried to set minimum size as 1.25 times of what getSize was returning, but that would make the frame larger and I can't make it smaller using methods like pack or setSize.

So my question is

  1. Can I make dragging respect the minimum size of the frame set using setMinimumSize?
  2. Can I make the frame size smaller than the size set using setMinimumSize without manually dragging?
camickr
  • 321,443
  • 19
  • 166
  • 288
  • Unfortunately this is a [bug](https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8221452), and the only workaround seems to use a ComponentListener to restore the right size, as detailed [here](https://news.kynosarges.org/2019/03/14/minimum-size-scaling-for-swing-windows); the problem with the workaround is that it cannot prevent the resizing, so you will see the window shrink a bit and enlarge again immediately. – Rocco May 13 '21 at 09:34

1 Answers1

0

I found a (dirty) trick: get the scaling factor and calculate the minimum size accordingly; then disable temporarily the setSize method when setting the scaled minimum size.

This is working in a single-screen environment, for multiple screens I have to work on it (basically check the graphics configuration when the window is moved and update the minimum size).

package test;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.geom.AffineTransform;

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

public class TestScaling extends JFrame {

    public TestScaling() {
        super("Test scaling");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel=new JPanel(new GridBagLayout());
        GridBagConstraints c=new GridBagConstraints();
        for (int i=0;i<10;i++) {
            for (int j=0;j<8;j++) {
                c.gridx=j;
                c.gridy=i;
                panel.add(new JButton(i+"x"+j),c);
            }
        }
        setContentPane(panel);
        pack();
        Dimension dorig=getSize();
        AffineTransform at=getGraphicsConfiguration().getDefaultTransform();
        Dimension dmin=new Dimension((int) (dorig.width*at.getScaleX()), (int) (dorig.height*at.getScaleY()));
        
        //A dirty trick, when workaround is true setSize(int,int) will not work
        //so setMinimumSize will not resize the window
        workaround=true;
        setMinimumSize(dmin);
        workaround=false;
    }
    
    protected boolean workaround;
    
    @Override
    public void setSize(int width, int height) {
        if (workaround) {
            return;
        }
        super.setSize(width, height);
    }
    
    
    public static void main(String[] args) {
        new TestScaling().setVisible(true);
    }
}
Rocco
  • 1,098
  • 5
  • 11