【问题标题】:Unexpected changes of the width attribute of a component组件的宽度属性发生意外变化
【发布时间】:2012-07-19 12:52:31
【问题描述】:

我注意到运行下面列出的程序有时会产生不良影响。

编辑:我已经简化了代码以使事情看起来更清晰。我正在绘制一个打印出当前组件大小的字符串。我已经覆盖了 Component 类中的 getPreferedSize() 方法,并将宽度和高度分别设置为 640 x 512。但是,运行程序后我仍然得到不同的结果:640 x 512 和 650 x 522。奇怪的是删除 frame.setResizable(false) 行修复了问题。但我希望窗口可以调整大小

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);
    }
}

【问题讨论】:

  • 对我能想到的行为的最佳猜测是,您使用setPreferredSize() 作为Content Pane。相反,您可以做的是覆盖getPreferredSize(),并使其返回您想要设置为JComponent 的首选大小的值。一个例子是hereanother hereand one More here
  • 为什么这种方法是有益的,看看@trashgod的wonderful answer
  • 感谢您的提示。正如您所指出的,我已经覆盖了该方法,并简化了代码。但是问题仍然出现,我不知道为什么。检查 OP 中的编辑。
  • 你很受欢迎并保持微笑:-) 我确实注意到,多次运行该程序确实会给你650 X 522,这是意料之外的。似乎frame.setResizable(...) 有问题,虽然我在Windoes 7 32 位平台上使用Java(TM) SE Runtime Environment (build 1.7.0_03-b05),但希望这不是1.7 的另一个错误:(
  • sscce+1。

标签: java swing


【解决方案1】:

setLocationByPlatform() 的调用必须在pack() 之后并在setVisible() 之前,否则几何将是错误的。没有理由对JFrame 进行子类化,我省略了DrawFrame 是下面的示例。请注意使用FontMetrics 在调整封闭容器大小时使文本居中。该方法对于学习布局很方便。

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);
    }
}

【讨论】:

  • 非常感谢您的努力。我非常感谢你的时间。但是尝试将 frame.setResizable(false) 添加到您的代码中,“+10px 错误”仍然出现。我把 setResizable 行放在 pack() 之前,假设应该是正确的。
  • 我无法重现您在pack() 之前使用setResizable(false) 描述的效果,但框架装饰因平台而异。什么主机操作系统?
  • @trashgod :我尝试过这个顺序,将setResizable(...) 作为第一行,在设置默认关闭行为之后,然后将组件添加到JFrame 然后pack() 然后Location 然后setVisible() ,虽然尝试了七八次之后,还是会弹出这个尺寸问题:(
  • @nIcEcOw:感谢您报告此结果。我无法使用 Java 1.6 在 Mac OS X 或 Ubuntu 上重现该效果。我猜 Windows 框架调整大小装饰是罪魁祸首。
【解决方案2】:

可能是因为原生窗口系统可能会忽略诸如设置帧大小之类的请求。
setSize() 方法也有类似的问题:

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

"该方法改变了几何相关的数据。因此,原生 窗口系统可能会忽略此类请求,或者它可能会修改 请求的数据,以便以某种方式放置 Window 对象并调整其大小 与桌面设置密切对应。”

简单测试,试试:

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

类似的设置可能会被忽略。

也请查看此主题:setSize() doesn't work for JFrame

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多