首页 > 解决方案 > 使用 JWindow 时结果不一致

问题描述

我正在编写这个程序来在 JWindow 中显示 JProgressbar。但是在同一台机器上运行这个程序而不做任何更改,每次都会显示不同的结果。大多数时候它显示空的 JWindow,里面没有任何东西。其他时候,它显示了我期望它出现的方式。我不知道出了什么问题。

我尝试过使用 JFrame。然后它一直完美地工作。但我想使用 JWindow。

这是我的代码:

package des;

import javax.swing.*;
import java.awt.*;

public class Test extends JWindow {
    JPanel panel = new JPanel();
    JLabel messageLabel = new JLabel();
    JProgressBar progressBar = new JProgressBar(0, 100);
    Test() {
        setVisible(true);
        setSize(480, 100);
        setLocationRelativeTo(null);//put it in center of screen

        messageLabel.setText("Hello World");
        messageLabel.setAlignmentX(JLabel.CENTER);
        progressBar.setValue(0);

        panel.setLayout(new BorderLayout());
        panel.add(messageLabel, BorderLayout.CENTER);
        panel.add(progressBar, BorderLayout.SOUTH);
        panel.setBackground(Color.cyan);
        add(panel,BorderLayout.CENTER);



    }

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

我在 intelliJ 的 Windows 10 64bit 中运行。这是我的 java -version:

openjdk version "12.0.1" 2019-04-16
OpenJDK Runtime Environment (build 12.0.1+12)
OpenJDK 64-Bit Server VM (build 12.0.1+12, mixed mode, sharing)

标签: javaswingjwindow

解决方案


调用setVisible(true)将触发事件调度线程 (EDT)。一旦运行,每个更新 UI 的调用都应该在 EDTSwingUtilities.invokeLater()运行,例如通过调用.

该规则有一些例外,当对象不可见(因此未呈现)时,明显地在构造函数中调用 UI 更新。一旦它变得可见,此类调用应推迟到 EDT。

所以你应该在你的构造函数中布局你的 GUI,并且setVisible(true)只在最后调用,一旦一切都准备好渲染。

正如@camickr 所指出的,所有UI 对象的构建也应该推迟到 EDT。不这样做可能会导致未定义的行为(即它可能工作也可能不工作,因为它没有由 JSR 指定)

关于为什么它没有显示,我再次引用@camickr 的评论:

代码不起作用的原因是在 GUI 可见之后添加了组件。默认情况下,组件的默认大小为 (0, 0)。所以没有什么可画的。如果您将组件添加到可见的 GUI,那么您需要revalidate()repaint()组件被添加到的容器,以便可以调用布局管理器。


推荐阅读