- 当您使用空布局时,you完全负责确保添加的组件具有正确的位置和size(不是首选尺寸)设置。
- 您几乎不应该使用空布局。
- Wouldn't this sort of thing work better by creating a logical class to represent the Circle, not a component? Then your drawing JPanel could hold a collection of logical circles, and the drawing JPanel could be responsible for drawing each Circle in its paintComponent method.
Edit
您的评论/我的回复:
当你说永远不要使用绝对布局时,我工作的公司总是只使用绝对布局。
有时它很有用,但不适用于创建典型的组件填充 GUI。否则 GUI 会变得很难修改和维护。
当您指的是逻辑类时,您指的是仅创建一个圆的类。
是的,它包含了该圆的所有必要属性,例如它的颜色、位置、运动等。
然后 Jpanel 会绘制每个圆圈。
是的。我想象绘图 JPanel 有一个ArrayList<MyCircle>
其中,paintComponent 方法迭代此列表。
当你说 Size 时,这是 JComponent 中的一个属性。
我认为它是 Component(JComponent 的父级)的属性。如果使用空布局,则所有组件must指定它们的大小和位置。否则,组件默认位置为 [0, 0],大小为 [0, 0]。
Edit 2
public Dimension Size(int a, int b) {
Dimension d = new Dimension();
d.width = a;
d.height = b;
return d;
}
这是我用于首选尺寸的代码。我不知道为什么这不起作用。
此代码对 Component/JComponent 的大小或 PreferredSize 属性没有影响。它对你没有帮助,我并不感到惊讶。你要么必须重写getSize()
or getPreferredSize()
或显式调用setSize(...)
or getPreferredSize(...)
更改属性的状态。
我将尝试使用不同的布局管理器并查看,但我会看到一个布局管理器或另一个布局管理器之间的差异。
我不知道如何解释这一点。
Edit 3
你说:
我在一家公司工作,我们一直使用绝对布局。绝对布局怎么会不如 BorderLayout() 那样好呢?对我来说,BorderLayout() 更难实现。或者是使用 Jframe() 和 BorderLayout,然后将 Jpanel 插入到已经存在的位置,该位置也已经是 BorderLayout()。我总是很难在与 BorderLayout() 不同的布局中正确获取按钮和位置。您可以发布一个比以下更容易使用的示例吗
我猜您想要一个使用布局管理器比使用绝对定位更容易的示例。
让我们以一个非常简单的计算器为例,它带有用于数字输入和简单操作的按钮。这个例子又是very基本的,非功能性的,但用于说明布局的使用。我可以轻松地将按钮放置在 GridLayout-使用 JPanel 中,然后将该按钮 JPanel 放置到 BorderLayout-使用 JPanel 中的 BorderLayout.CENTER 位置,并与 JTextField 一起显示,放置在相同的 BorderLayout-使用 JPanel 中的 BorderLayout.PAGE_START位置:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.*;
public class CalcEg {
private static final float BTN_FONT_SIZE = 20f;
private static final String[][] BTN_LABELS = {
{"7", "8", "9", "-"},
{"4", "5", "6", "+"},
{"1", "2", "3", "/"},
{"0", ".", " ", "="}
};
private static final int GAP = 4;
private JPanel mainPanel = new JPanel(new BorderLayout(GAP, GAP));
private JPanel buttonPanel = new JPanel();
private JTextField display = new JTextField();
public CalcEg() {
int rows = BTN_LABELS.length;
int cols = BTN_LABELS[0].length;
buttonPanel.setLayout(new GridLayout(rows, cols, GAP, GAP));
for (String[] btnLabelRow : BTN_LABELS) {
for (String btnLabel : btnLabelRow) {
if (btnLabel.trim().isEmpty()) {
buttonPanel.add(new JLabel());
} else {
JButton btn = createButton(btnLabel);
buttonPanel.add(btn);
}
}
}
display.setFont(display.getFont().deriveFont(BTN_FONT_SIZE));
display.setEditable(false);
display.setFocusable(false);
display.setBackground(Color.white);
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.add(buttonPanel, BorderLayout.CENTER);
mainPanel.add(display, BorderLayout.PAGE_START);
}
private JButton createButton(String btnLabel) {
JButton button = new JButton(btnLabel);
button.setFont(button.getFont().deriveFont(BTN_FONT_SIZE));
return button;
}
public JComponent getMainComponent() {
return mainPanel;
}
private static void createAndShowGui() {
CalcEg mainPanel = new CalcEg();
JFrame frame = new JFrame("CalcEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
这将产生一个如下所示的计算器:
现在,您肯定可以说您可以使用空布局来生成它,并且setbounds(...)
,这一切都很好,但现在说您对这个计算器不满意,现在希望它具有一些科学计算功能。说你现在想要添加按钮对于平方、平方根、指数和对数,但不仅如此,假设您希望在显示屏下方、数字和基本操作按钮上方添加按钮。如果您要使用空布局来执行此操作,则必须重新定位添加的任何新组件下方和右侧的所有组件,并且必须扩大 JTextField 的大小,所有计算都很繁琐且容易出现问题错误。
如果您使用布局管理器,则只需添加一行代码,实际上是向数组添加一行:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.*;
public class CalcEg {
private static final float BTN_FONT_SIZE = 20f;
private static final String[][] BTN_LABELS = {
{"sqr", "sqrt", "exp", "log"}, // ******* Line Added Here *********
{"7", "8", "9", "-"},
{"4", "5", "6", "+"},
{"1", "2", "3", "/"},
{"0", ".", " ", "="}
};
private static final int GAP = 4;
private JPanel mainPanel = new JPanel(new BorderLayout(GAP, GAP));
private JPanel buttonPanel = new JPanel();
private JTextField display = new JTextField();
public CalcEg() {
int rows = BTN_LABELS.length;
int cols = BTN_LABELS[0].length;
buttonPanel.setLayout(new GridLayout(rows, cols, GAP, GAP));
for (String[] btnLabelRow : BTN_LABELS) {
for (String btnLabel : btnLabelRow) {
if (btnLabel.trim().isEmpty()) {
buttonPanel.add(new JLabel());
} else {
JButton btn = createButton(btnLabel);
buttonPanel.add(btn);
}
}
}
display.setFont(display.getFont().deriveFont(BTN_FONT_SIZE));
display.setEditable(false);
display.setFocusable(false);
display.setBackground(Color.white);
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.add(buttonPanel, BorderLayout.CENTER);
mainPanel.add(display, BorderLayout.PAGE_START);
}
private JButton createButton(String btnLabel) {
JButton button = new JButton(btnLabel);
button.setFont(button.getFont().deriveFont(BTN_FONT_SIZE));
return button;
}
public JComponent getMainComponent() {
return mainPanel;
}
private static void createAndShowGui() {
CalcEg mainPanel = new CalcEg();
JFrame frame = new JFrame("CalcEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
这将导致这个 GUI:
这又是一个非常简单的示例,但一般原则适用于任何包含 JButtons、JTextComponents 等组件的 GUI。