1

所以我做了一个WindowDisp扩展类JFrame

public class WindowDisp extends JFrame{

    private static final long serialVersionUID = 3245091489595286109L;

    private int height, width;
    private JPanel panel;
    private JLabel mainPane;

    public WindowDisp(int a, int b, int pw, int ph){
        height = a;
        width = b;

        Container c = getContentPane();
        c.setPreferredSize(new Dimension(width, height));
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);

        mainPane = new JLabel();
        mainPane.setPreferredSize(new Dimension(pw, ph));
        mainPane.setFont(new Font("Monospaced", Font.PLAIN, 10));

        panel = new JPanel();
        panel.setPreferredSize(getSize());
        panel.add(mainPane);
        add(panel);

        setVisible(true);
        pack();
    }

    public static void main(String[] args){
        WindowDisp win = new WindowDisp(400, 400, 400, 400);
    }
}

在我的Main班级中,我声明了一个WindowDispwhere 它的heightandwidth等于它的phand pw。然而,问题是,在运行我的程序时,白色的“条”出现在JPanel框架中的默认背景颜色周围。它们似乎从右侧和底部填充面板,就好像框架中没有面板没有占用的空间一样,但是,如果我的编码正确,面板应该与框架的大小相同ContentPane,如果它不是?

我发现删除这两个pack();命令中的任何一个都不会删除这些条,尽管删除第一个命令会将它们更改为黑色,而删除第二个命令会使右侧的那个变宽。当然,同时删除它们会导致框架的大小与其ContentPane. 此外,add(panel);完全删除没有效果。

我无法弄清楚这段代码中的什么导致我的框架中出现了看似空白的空间,而且,在我的程序中,传递给Window构造函数的所有四个值都是相等的。看起来很奇怪的是,即使我只是删除add(panel);,也没有任何改变 vi 的白色填充。事实上,我可以注释掉从mainPane =...to的所有内容add(panel);,这根本不会影响它。

4

4 回答 4

3

我似乎无法准确地复制这个问题,但我想我可以复制想要的结果......

在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class WindowDisp extends JFrame {

    private static final long serialVersionUID = 3245091489595286109L;

    private JPanel panel;
    private JLabel mainPane;

    public WindowDisp(int width, int height) {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);

        mainPane = new JLabel();
        mainPane.setBorder(new LineBorder(Color.BLUE));
        mainPane.setFont(new Font("Monospaced", Font.PLAIN, 10));

        panel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(width, height);
            }
        };
        panel.setLayout(new BorderLayout());
        panel.setBorder(new EmptyBorder(4, 4, 4, 4));
        panel.add(mainPane);
        add(panel);

        pack();
        setLocationRelativeTo(null);
        setVisible(true);

        System.out.println(getSize());
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                WindowDisp win = new WindowDisp(400, 400);
            }
        });
    }
}

突然出现在我身上的事情(作为问题)......

  • panel.setPreferredSize(getSize());- 窗口的大小通常大于窗口大小,这是因为窗口有装饰,这些装饰画在框架边界内。 pack使用布局信息(以及preferredSize组件的间接信息)来确保内容具有它所要求的空间量,然后围绕它调整窗口大小以适应框架装饰。通过调用getContentPane().setPreferredSize,您将取代布局管理器可能提供的任何信息,并忽略其他组件的要求。这是我们建议您永远不要打电话的(许多)原​​因之一setPreferredSize,永远......

重申...

Container c = getContentPane();
c.setPreferredSize(new Dimension(width, height));

强制将窗口的可视空间设置为width/height值 (400x400)。此容器将不再能够对其内容的更改做出反应,并且总是更喜欢400x400

mainPane.setPreferredSize(new Dimension(pw, ph));

将首选大小设置mainPane400x400(根据您的示例)。同样,它总是更喜欢400x400,但设置内容窗格的简单事实意味着该值实际上被忽略了......

panel.setPreferredSize(getSize());

现在,棺材上的钉子。这将设置为panel与框架相同的大小,但是,框架大于contentPane(400x400 + 框架装饰),它也在框架内偏移(它不会定位在 0x0,但会偏移以便它出现在框架的标题和右边框下方),但可以扩展到框架边界之外

这些问题的组合都对你不利。与其担心框架大小,不如担心框架显示的大小需求/要求。

每个操作系统使用不同的帧装饰,所以实际的,物理的,帧大小在不同的操作系统上会有所不同,但如果你专注于内容的要求,你就不会在意

于 2015-02-18T01:01:30.817 回答
2

请参阅我应该避免在 Java Swing 中使用 set(Preferred|Maximum|Minimum)Size 方法吗? (是的。)

而是对空白使用布局填充和边框。最后,调用pack()以确保框架与显示组件和空白空间所需的(最小尺寸)一样大。

窗口显示

import java.awt.Font;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class WindowDisp extends JFrame {

    private JPanel panel;
    private JLabel mainLabel;

    public WindowDisp(int t, int l, int b, int r, String title) {
        super(title);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setResizable(false);
        setLocationByPlatform(true);

        mainLabel = new JLabel("Hello Padding!");
        mainLabel.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 10));
        mainLabel.setBorder(new EmptyBorder(t, l, b, r));

        panel = new JPanel();
        panel.add(mainLabel);
        add(panel);

        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                new WindowDisp(50, 150, 50, 150, "Window 1");
                new WindowDisp(50, 100, 50, 100, "Window 2");
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
于 2015-02-18T01:32:16.903 回答
1

到目前为止,解决这个烦人问题的最佳补丁如下。调用方法的位置无关紧要setResizable(false)。只需在您之后添加这段代码setVisible(true)

private void sizeBugPatch() {
    while (frame.getWidth() > yourWidth) {
        frame.pack();
    }
}

您以任何可能的方式设置yourWidth宽度在哪里,无论是手动还是通过覆盖setPreferredSize方法。解释很简单,frame.pack()似乎以frame.setResizable(boolean b)某种方式重置。您可以使用 anif而不是while循环,但我更愿意while排除即使在 second 之后窗口仍然会超大的情况pack()

于 2016-07-21T18:56:04.133 回答
0

我从摇摆日学到的一件事是永远不要将 setPreferred... 与 pack() 混合使用。您要么使用其中一个。

试试这个代码:

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

public class WindowDisp extends JFrame {

    private int height, width;
    private JPanel panel;
    private JLabel mainPane;

    public WindowDisp(int a, int b, int pw, int ph){
        height = a;
        width = b;

        Container c = getContentPane();
//        c.setPreferredSize(new Dimension(width, height));

        mainPane = new JLabel("Hello from Pane");
        mainPane.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 10));

        panel = new JPanel();
//        panel.setPreferredSize(new Dimension(pw, ph));
        panel.add(mainPane);
        c.add(panel, BorderLayout.CENTER);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);
        pack();
        setVisible(true);
    }

    public static void main(String[] args){
        WindowDisp win = new WindowDisp(400, 400, 400, 400);
    }
}

输出:

在此处输入图像描述

于 2015-02-18T01:18:52.430 回答