JFrame的大小如何实际起作用?

时间:2015-05-28 23:28:48

标签: java swing jframe

我对我正在做的事情毫无目的,只是用Java Swing来解决问题。我现在拥有的是这三个变量:

    int[] gridIterations = {10,10}; //how many JButtons are made each row/column
    int[] frameSize = {600,600}; //size of the JFrame
    int[] gridSize = {60,60}; //by gridSize, I mean size of the JButtons

我还有一个嵌套的for循环,它使用这些变量来创建一个JButtons网格。我希望期望网格完全适合JFrame,但这是结果:

Grids cut off at the bottom and right edges of JFrame

经过一些测试后,我意识到如果大小为(615, 631),框架实际上只适合所有JButton但是我想知道,为什么它只适用于这些参数,以及为什么在所有数字中,它是那些?根据我的理解,60 * 10的简单计算应该等于600并且成功地将所有按钮都放入JFrame中,但我很可能忽略了某些东西。那可能是什么?感谢。

2 个答案:

答案 0 :(得分:4)

JFrame的大小包括其insets。这基本上意味着标题栏和边框。

GridLayout将为您完美地完成这项工作,而且工作量更少。

grid layout

class GridButtons implements Runnable {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new GridButtons(4, 5));
    }

    final int rows;
    final int cols;

    GridButtons(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
    }

    @Override
    public void run() {
        JFrame frame = new JFrame();
        JPanel grid = new JPanel(new GridLayout(rows, cols));

        for (int i = 0; i < (rows * cols); ++i) {
            grid.add(new JButton() {
                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(60, 60);
                }
            });
        }

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

答案 1 :(得分:4)

很多内容归结为内容和布局管理器的要求。而不是看你想要框架的“有多大”,而是关注内容所需的空间量。然后框架将“包装”在此周围。

这意味着框架将“内容大小+框架边框大小”大。

JFrame#pack会考虑内容的首选大小,并自动添加框架边框插入内容。

所以,你需要做的唯一事情就是在完成向其添加内容后调用JFrame#pack

所以,根据你的代码:

public class Testing {

        public static void main(String[] args) {
                JFrame frame = new JFrame("hi");

                for (int i = 0; i < 10; i++) {
                        JButton a = new JButton();
                        a.setSize(20,20);
                        a.setLocation(20*i, 0);
                        frame.getContentPane().add(a);

                }
                frame.setLayout(null);
                frame.pack();
                frame.setVisible(true);
        }

}

您正在使用null布局。 JFrame#pack将使用布局管理器提供的信息来确定整体内容的“首选”大小。

避免使用null布局,像素完美布局是现代ui设计中的一种幻觉。影响组件个体大小的因素太多,您无法控制。 Swing旨在与布局管理器一起工作,放弃这些将导致问题和问题的结束,您将花费越来越多的时间来纠正。

而是专注于绝对体验,它可以在OS(甚至是具有相同操作系统的不同PC)之间变化,专注于用户体验。

正如已经证明的那样,您可以使用GridLayout

轻松实现此功能

GridLayout

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridLayout(10, 10, 0, 0));
            for (int index = 0; index < 10 * 10; index++) {
                JButton btn = new JButton(String.valueOf(index)) {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(50, 50);
                    }
                };
                add(btn);
            }
        }

    }

}

如果您需要更复杂的管理(即广度深度),您可以使用GridBagLayout代替

请查看Laying Out Components Within a ContainerHow to Use GridLayoutHow to Use GridBagLayout了解详情;)