3

I have noticed that running the program I'm listing below sometimes produces an unwanted effect.

EDIT: I've simplified the code to make things look clear. I'm drawing a String which prints out the current component size. I've overriden the getPrefferedSize() method in the Component class and set width and height to 640 x 512 respectively. However, I'm still getting different results after running the program: 640 x 512 and 650 x 522. Weird thing is removing the frame.setResizable(false) line fixes things. But I want the window to be resizable

import java.awt.*;

import javax.swing.*;

public class DrawTest
{
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                DrawFrame frame = new DrawFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setResizable(false);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}


class DrawFrame extends JFrame
{

    private static final long serialVersionUID = 1L;
    public DrawFrame()
    {
        setTitle("DrawTest");
        setLocationByPlatform(true);
        Container contentPane = getContentPane();
        DrawComponent component = new DrawComponent();
        contentPane.add(component);
    }

}

class DrawComponent extends JComponent
{
    private static final long serialVersionUID = 1L;
    public Dimension getPreferredSize() {
        return new Dimension(640, 512);
    }

    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;         
        String msg = getWidth() + " x " + getHeight();      
        g2.setPaint(Color.BLUE);
        g2.drawString(msg, getWidth()/2, getHeight()/2);
    }
}

Eric Robinson
  • 2,025
  • 14
  • 22
Raidmaster
  • 603
  • 2
  • 7
  • 15
  • The Best guess for the behavior I can think of is, that you using `setPreferredSize()` for the `Content Pane`. Instead of this what you can do is override the [getPreferredSize()](http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#getPreferredSize()), and make it return a value that you wanted to set as a Preferred Size for the `JComponent`. one example is [here](http://stackoverflow.com/a/11372350/1057230), [another here](http://stackoverflow.com/a/11534873/1057230), [and one More here](http://stackoverflow.com/a/11376322/1057230) – nIcE cOw Jul 19 '12 at 15:28
  • 1
    As to why this approach is beneficial, have a look at this [wonderful answer](http://stackoverflow.com/a/11377526/1057230) by @trashgod – nIcE cOw Jul 19 '12 at 15:30
  • 1
    Thanks for hints. I've overriden the method as you pointed out, and simplified the code. However problem still appears and I have no idea why. Check the edit in OP. – Raidmaster Jul 19 '12 at 16:40
  • 1
    You are MOST WELCOME and KEEP SMILING :-) I did noticed, running the program several times did gives you `650 X 522` which is not expected. Seems like that `frame.setResizable(...)` is at fault, though I am using `Java(TM) SE Runtime Environment (build 1.7.0_03-b05)` on Windoes 7 32-bit Platform, Hope it's not another bug of 1.7 :( – nIcE cOw Jul 19 '12 at 16:54
  • +1 for [sscce](http://sscce.org/). – trashgod Jul 19 '12 at 19:23

2 Answers2

3

The call to setLocationByPlatform() must follow pack() and precede setVisible(), or the geometry will be wrong. Absent a reason to subclass JFrame, I have elided DrawFrame is the example below. Note the use of FontMetrics to keep the text centered as the enclosing container is resized. The approach is handy for learning layouts.

enter image description here

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

public class DrawTest {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame("DrawTest");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new DrawComponent());
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}

class DrawComponent extends JComponent {

    private static final long serialVersionUID = 1L;

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(320, 240);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        String msg = getWidth() + " x " + getHeight();
        g2.setPaint(Color.BLUE);
        int w = (getWidth() - g.getFontMetrics().stringWidth(msg)) / 2;
        g2.drawString(msg, w, getHeight() / 2);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thank you very much for your effort. I can't thank enough for your time. But try to add frame.setResizable(false) to your code and the "+10px bug" is still appearing. I put setResizable line before pack(), assuming that should be correct. – Raidmaster Jul 19 '12 at 20:00
  • I can't reproduce the effect you describe using `setResizable(false)` before `pack()`, but the frame decorations vary by platform. What host OS? – trashgod Jul 20 '12 at 00:27
  • @trashgod : I had tried this sequence, putting `setResizable(...)` as the first line, after setting default CLOSE Behavior, then added components to the `JFrame` then `pack()` then `Location` and then `setVisible()` , though still after seven or eight tries, this size issue pops up :( – nIcE cOw Jul 20 '12 at 01:50
  • 1
    @nIcEcOw: Thank you for reporting this result. I am unable to reproduce the effect on Mac OS X or Ubuntu using Java 1.6. I'm guessing the Windows frame resize decorations are the culprit. – trashgod Jul 20 '12 at 01:52
3

Maybe because native windowing system may ignore such requests like set frame size.
setSize() method have similar problem:

http://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#setSize%28java.awt.Dimension%29

"The method changes the geometry-related data. Therefore, the native windowing system may ignore such requests, or it may modify the requested data, so that the Window object is placed and sized in a way that corresponds closely to the desktop settings."

Simple test, try:

public Dimension getPreferredSize() {
    return new Dimension(2000, 1000);
}

similar settings probably will be ignore.

check also this topic: setSize() doesn't work for JFrame

Community
  • 1
  • 1
Jacob
  • 31
  • 1