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