JFrame在内容周围显示白条

时间:2015-02-18 00:58:27

标签: java swing jframe jpanel contentpane

所以我创建了一个扩展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课程中,我宣布WindowDisp heightwidth等于其phpw。但问题是,在运行我的程序时,框架中的默认背景颜色JPanel周围会出现白色“条形”。它们似乎是从右侧和底部填充面板,好像框架中没有占用面板的空间,但是,如果我的编码是正确的,面板应该与框架的{{1 ,不是吗?

我发现删除这两个ContentPane命令中的任何一个都不会删除这些条形图,虽然删除第一个条形图会将它们更改为黑色,而删除第二个条形图会使第二个条形图更宽。当然,删除它们会导致帧与pack();的大小不同。此外,完全删除ContentPane无效。

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

4 个答案:

答案 0 :(得分:3)

我似乎无法完全复制这个问题,但我想我可以复制所需的结果......

enter image description here

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

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

panel.setPreferredSize(getSize());
现在,钉在棺材里。这将panel设置为与帧的大小相同,但是,帧大于contentPane(400x400 +帧装饰),它也在帧内偏移(它赢得了#t; t位于0x0,但将被偏移,使其显示在框架的标题和右边框下方,但可以扩展到框架边界

这些问题的组合都会对你不利。而不是担心框架大小,而是担心框架显示的尺寸需求/要求。

每个操作系统使用不同的框架装饰,因此实际的,物理的,框架尺寸在不同的操作系统上会有所不同,但如果你专注于内容的要求,你就不会关心

答案 1 :(得分:2)

请参阅Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?(是)。

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

WindowDisp

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

答案 2 :(得分:1)

到目前为止,针对此烦人问题的最佳补丁如下。你调用setResizable(false)方法的地方并不重要。只需在setVisible(true)之后添加这段代码。

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

yourWidth width ,您可以通过任何可能的方式设置,手动或通过覆盖setPreferredSize方法。解释非常简单,frame.pack()似乎以某种方式重置frame.setResizable(boolean b)。您可以使用if代替while循环,但我更喜欢while来排除即使在第二个pack()之后窗口仍然是超大的情况。

答案 3 :(得分: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);
    }
}

输出:

enter image description here