JFrame 的大小实际上是如何工作的?
How does the sizing of a JFrame actually work?
我真正做的事情没有任何目的,只是用 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 循环,它使用这些变量来创建 JButton 网格。我会 期望 网格完全适合 JFrame,但这是结果:
经过一些测试后,我意识到如果尺寸为 (615, 631)
,框架实际上只会适合所有 JButtons 但我想知道,为什么它只适合这些参数,以及为什么,所有数字,会是 那些吗? 据我了解,60 * 10 的简单计算应该等于 600 并成功地将所有按钮放入 JFrame,但我很可能忽略了一些东西。那会是什么?谢谢
JFrame 的大小包括其插图。这基本上意味着标题栏和边框。
GridLayout 将以更少的努力为您完美地完成这项工作。
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);
}
}
很大程度上取决于内容和布局管理器的要求ui。而不是寻找 "how big" 你想要的框架,关注内容需要的 space 数量。然后框架将 "pack" 围绕此。
这意味着框架会"content size + frame border size"大。
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
将使用布局管理器提供的信息来确定整体内容的 "preferred" 大小。
避免使用 null
布局,像素完美布局是现代 ui 设计中的一种错觉。影响组件个体大小的因素太多,none 是您可以控制的。 Swing 旨在与核心的布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正。
而不是专注于绝对,这在 OS 之间是可变的(甚至是具有相同 OS 的不同 PC),专注于用户体验。
正如已经证明的那样,您可以使用 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 Container, How to Use GridLayout and How to Use GridBagLayout 了解更多详情 ;)
我真正做的事情没有任何目的,只是用 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 循环,它使用这些变量来创建 JButton 网格。我会 期望 网格完全适合 JFrame,但这是结果:
经过一些测试后,我意识到如果尺寸为 (615, 631)
,框架实际上只会适合所有 JButtons 但我想知道,为什么它只适合这些参数,以及为什么,所有数字,会是 那些吗? 据我了解,60 * 10 的简单计算应该等于 600 并成功地将所有按钮放入 JFrame,但我很可能忽略了一些东西。那会是什么?谢谢
JFrame 的大小包括其插图。这基本上意味着标题栏和边框。
GridLayout 将以更少的努力为您完美地完成这项工作。
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);
}
}
很大程度上取决于内容和布局管理器的要求ui。而不是寻找 "how big" 你想要的框架,关注内容需要的 space 数量。然后框架将 "pack" 围绕此。
这意味着框架会"content size + frame border size"大。
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
将使用布局管理器提供的信息来确定整体内容的 "preferred" 大小。
避免使用 null
布局,像素完美布局是现代 ui 设计中的一种错觉。影响组件个体大小的因素太多,none 是您可以控制的。 Swing 旨在与核心的布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正。
而不是专注于绝对,这在 OS 之间是可变的(甚至是具有相同 OS 的不同 PC),专注于用户体验。
正如已经证明的那样,您可以使用 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 Container, How to Use GridLayout and How to Use GridBagLayout 了解更多详情 ;)