Java 中 GUI 编程的奇怪问题
Weird problem with GUI programming in Java
我在Java中做了一个简单的GUI。问题是,当我在按钮和复选按钮之前的框架上添加标签时,将鼠标悬停在按钮上时会出现奇怪的闪烁,并且 GUI 看起来不正确。但是当我在按钮和复选按钮之后添加标签时,一切正常。为什么会这样?
这是我的代码:
package javaapplication13;
import java.awt.*;
import javax.swing.*;
public class JavaApplication13 {
public static void main(String[] args) {
ButtonFrame bf = new ButtonFrame();
}
}
class ButtonFrame extends JFrame {
public ButtonFrame() {
JButton b1 = new JButton("1. Dugme");
JButton b2 = new JButton("2. Dugme");
JLabel l1 = new JLabel();
JCheckBox c1 = new JCheckBox("Prvo dugme");
JCheckBox c2 = new JCheckBox("Drugo dugme");
Container cp = getContentPane();
setTitle("Dugme");
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.add(b1);
this.add(b2);
this.add(c1);
this.add(c2);
this.add(l1);
b1.setBounds(20, 30, 90, 20);
b2.setBounds(20,70,90,20);
l1.setBounds(70,120,90,20);
c1.setBounds(120,30,120,20);
c2.setBounds(120,70,120,20);
l1.setText("");
}
}
这是因为您不想使用默认值 LayoutManager
,因为您在组件上使用了严格的界限。使用
删除布局管理器
setLayout(null);
它会按预期工作
public ButtonFrame(){
setLayout(null); //this will do the trick
JButton b1 = new JButton("1. Dugme");
...rest of your code
}
我在 Windows 10 和 JDK 17 的计算机上复制和 运行 你的代码时,我没有看到你声称的闪烁。但是,当我改变你的代码并在添加按钮和复选框之前将标签添加到框架中(如您在问题中所述),我确实看到“闪烁”。
虽然你已经接受了@Antoniosss, it is not recommended to not use a layout manager. Refer to the following excerpts from Doing Without a Layout Manager
Although it is possible to do without a layout manager, you should use a layout manager if at all possible.
If a container holds components whose size is not affected by the container's size or by font, look-and-feel, or language changes, then absolute positioning might make sense.
您的 GUI 适用的布局管理器之一是 GridBagLayout,尽管那不是唯一合适的。下面的代码显示了如何。 (请注意,在下面的代码中,我设置了 JLabel
的文本,以便您可以看到它。)
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BtnFrame {
private void createAndDisplayGui() {
JFrame frame = new JFrame("Dugme");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
createForm(frame.getContentPane());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void createForm(Container contentPane) {
if (contentPane instanceof JComponent) {
JComponent jCmpt = (JComponent) contentPane;
jCmpt.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.insets.top = 5;
JButton b1 = new JButton("1. Dugme");
contentPane.add(b1, gbc);
gbc.gridx = 1;
JCheckBox c1 = new JCheckBox("Prvo dugme");
contentPane.add(c1, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
JButton b2 = new JButton("2. Dugme");
contentPane.add(b2, gbc);
gbc.gridx = 1;
JCheckBox c2 = new JCheckBox("Drugo dugme");
contentPane.add(c2, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.CENTER;
JLabel l1 = new JLabel("label");
contentPane.add(l1, gbc);
}
public static void main(String[] args) {
final BtnFrame gui = new BtnFrame();
EventQueue.invokeLater(() -> gui.createAndDisplayGui());
}
}
这是应用程序的屏幕截图。
在您的代码中将布局管理器设置为 null 时(如@Antoniosss 在他的回答中所说),GUI 看起来像下面的屏幕截图。 (同样,我还设置了 JLabel
的文本,以便您可以看到它。)
如您所见,这两个屏幕截图几乎完全相同。
为了完整起见,这是您的代码,经过我的更改后,生成了上述屏幕截图。如您所见,我移动了行 this.add(l1)
并添加了行 cp.setLayout(null)
.
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ButtonFrame extends JFrame {
public ButtonFrame(){
JButton b1 = new JButton("1. Dugme");
JButton b2 = new JButton("2. Dugme");
JLabel l1 = new JLabel();
JCheckBox c1 = new JCheckBox("Prvo dugme");
JCheckBox c2 = new JCheckBox("Drugo dugme");
Container cp = getContentPane();
cp.setLayout(null); // Added this line.
setTitle("Dugme");
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.add(l1);
this.add(b1);
this.add(b2);
this.add(c1);
this.add(c2);
// this.add(l1);
b1.setBounds(20, 30, 90, 20);
b2.setBounds(20,70,90,20);
l1.setBounds(70,120,90,20);
c1.setBounds(120,30,120,20);
c2.setBounds(120,70,120,20);
l1.setText("label");
}
public static void main(String[] args) {
ButtonFrame bf = new ButtonFrame();
}
}
我在Java中做了一个简单的GUI。问题是,当我在按钮和复选按钮之前的框架上添加标签时,将鼠标悬停在按钮上时会出现奇怪的闪烁,并且 GUI 看起来不正确。但是当我在按钮和复选按钮之后添加标签时,一切正常。为什么会这样?
这是我的代码:
package javaapplication13;
import java.awt.*;
import javax.swing.*;
public class JavaApplication13 {
public static void main(String[] args) {
ButtonFrame bf = new ButtonFrame();
}
}
class ButtonFrame extends JFrame {
public ButtonFrame() {
JButton b1 = new JButton("1. Dugme");
JButton b2 = new JButton("2. Dugme");
JLabel l1 = new JLabel();
JCheckBox c1 = new JCheckBox("Prvo dugme");
JCheckBox c2 = new JCheckBox("Drugo dugme");
Container cp = getContentPane();
setTitle("Dugme");
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.add(b1);
this.add(b2);
this.add(c1);
this.add(c2);
this.add(l1);
b1.setBounds(20, 30, 90, 20);
b2.setBounds(20,70,90,20);
l1.setBounds(70,120,90,20);
c1.setBounds(120,30,120,20);
c2.setBounds(120,70,120,20);
l1.setText("");
}
}
这是因为您不想使用默认值 LayoutManager
,因为您在组件上使用了严格的界限。使用
setLayout(null);
它会按预期工作
public ButtonFrame(){
setLayout(null); //this will do the trick
JButton b1 = new JButton("1. Dugme");
...rest of your code
}
我在 Windows 10 和 JDK 17 的计算机上复制和 运行 你的代码时,我没有看到你声称的闪烁。但是,当我改变你的代码并在添加按钮和复选框之前将标签添加到框架中(如您在问题中所述),我确实看到“闪烁”。
虽然你已经接受了@Antoniosss
Although it is possible to do without a layout manager, you should use a layout manager if at all possible.
If a container holds components whose size is not affected by the container's size or by font, look-and-feel, or language changes, then absolute positioning might make sense.
您的 GUI 适用的布局管理器之一是 GridBagLayout,尽管那不是唯一合适的。下面的代码显示了如何。 (请注意,在下面的代码中,我设置了 JLabel
的文本,以便您可以看到它。)
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class BtnFrame {
private void createAndDisplayGui() {
JFrame frame = new JFrame("Dugme");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
createForm(frame.getContentPane());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void createForm(Container contentPane) {
if (contentPane instanceof JComponent) {
JComponent jCmpt = (JComponent) contentPane;
jCmpt.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.insets.top = 5;
JButton b1 = new JButton("1. Dugme");
contentPane.add(b1, gbc);
gbc.gridx = 1;
JCheckBox c1 = new JCheckBox("Prvo dugme");
contentPane.add(c1, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
JButton b2 = new JButton("2. Dugme");
contentPane.add(b2, gbc);
gbc.gridx = 1;
JCheckBox c2 = new JCheckBox("Drugo dugme");
contentPane.add(c2, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.CENTER;
JLabel l1 = new JLabel("label");
contentPane.add(l1, gbc);
}
public static void main(String[] args) {
final BtnFrame gui = new BtnFrame();
EventQueue.invokeLater(() -> gui.createAndDisplayGui());
}
}
这是应用程序的屏幕截图。
在您的代码中将布局管理器设置为 null 时(如@Antoniosss 在他的回答中所说),GUI 看起来像下面的屏幕截图。 (同样,我还设置了 JLabel
的文本,以便您可以看到它。)
如您所见,这两个屏幕截图几乎完全相同。
为了完整起见,这是您的代码,经过我的更改后,生成了上述屏幕截图。如您所见,我移动了行 this.add(l1)
并添加了行 cp.setLayout(null)
.
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ButtonFrame extends JFrame {
public ButtonFrame(){
JButton b1 = new JButton("1. Dugme");
JButton b2 = new JButton("2. Dugme");
JLabel l1 = new JLabel();
JCheckBox c1 = new JCheckBox("Prvo dugme");
JCheckBox c2 = new JCheckBox("Drugo dugme");
Container cp = getContentPane();
cp.setLayout(null); // Added this line.
setTitle("Dugme");
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
this.add(l1);
this.add(b1);
this.add(b2);
this.add(c1);
this.add(c2);
// this.add(l1);
b1.setBounds(20, 30, 90, 20);
b2.setBounds(20,70,90,20);
l1.setBounds(70,120,90,20);
c1.setBounds(120,30,120,20);
c2.setBounds(120,70,120,20);
l1.setText("label");
}
public static void main(String[] args) {
ButtonFrame bf = new ButtonFrame();
}
}