gpt4 book ai didi

java - 为什么 InvokeLater 导致我的 JFrame 无法正确显示?

转载 作者:搜寻专家 更新时间:2023-10-31 20:07:39 25 4
gpt4 key购买 nike

好吧,我已经阅读了整个网络的搜索,但我还没有找到解决我的问题的方法,也许我遗漏了一些简单的东西,因此我在这里......

我有一个相当大的项目,用于处理维修业务的工单。它全部连接到数据库,许多代码页和类。但我只是在前端添加了一小段代码,主要用于检查笔记区域中是否有新消息。

无论如何,我显示一个带有两个 JLabel 的简单 JFrame,同时一个单独的线程查询数据库。这一切都发生在程序的开始。问题是我的小“请稍等”JFrame 在等待期间出现了它的框架,但没有胆量,没有背景,也没有 JLabel程序加载,而不是数据库线程),它显示后记,但到那时它就失去了意义。

我写了下面的示例程序。它显示一个简单的 JFrame(CheckingMessagesGUI:一个带有两个 JLabelJFrame,仅此而已) hibernate 5 秒,然后显示示例(主程序) JFrame,然后立即关闭 (System.exit(0)) 在这个例子中,当然我的真实程序继续做更多。我发现 invokeLater 似乎是导致问题的原因。一旦 sleep 计时器用完,窗口就会显示,但显示它的代码是在 Thread.sleep 命令之前给出的,应该按正确的顺序完成吗?

我的问题是为什么 invokeLater 导致我的 JFrame 无法正确显示?

据我了解,invokeLater 的目的是让项目在正确的 AWT 事件线程上运行,这让我认为这个窗口会被正确绘制。无论如何,我确定我遗漏了一些明显的东西。我在下面的代码中注释掉了 invokeLater 部分,它运行正确,如果你把它放回去它不会......

非常感谢。

package javaapplication6;

public class Example extends javax.swing.JFrame {
public Example() {
System.out.println("Example started");
setBounds(100,100,200,200);

System.out.println("cmGUI instantiated");
CheckingMessagesGUI cmGUI = new CheckingMessagesGUI();
System.out.println("Set cmGUI visible");
cmGUI.setVisible(true);
cmGUI.validate();
try {
System.out.println("timer started");
Thread.sleep(5000);
System.out.println("timer done");
} catch(InterruptedException e){
}
System.exit(0);
}

public static void main(String[] args) {
/*java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() { */
System.out.println("Started");
System.out.println("example Instantiated");
Example example = new Example();
System.out.println("example visible");
example.setVisible(true);
/* }
});
*/
}
}

更新:澄清一下,我知道 Thread.sleep() 会阻止所有内容,但我的 CheckingMessagesGUI 不应该在我调用 sleep 之前已经完全绘制了吗?这就是问题所在。

最佳答案

invokeLater 在事件调度线程中运行 Runnable,该线程也用于更新 GUI。
您的 sleep 阻塞了此线程,因此 GUI 也不会得到服务,在您从 invokeLater 代码返回之前无法进行任何更新。
这就是为什么你不应该在这个线程中做任何长时间(耗时)的计算。它们应该在不同的(新)线程中完成。

The Event Dispatch Queue

Tasks on the event dispatch thread must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive.

您的代码可以更改为(未测试):

public Example(){
System.out.println("Example started");
setBounds(100,100,200,200);

System.out.println("cmGUI instantiated");
CheckingMessagesGUI cmGUI = new CheckingMessagesGUI();
System.out.println("Set cmGUI visible");
cmGUI.setVisible(true);
cmGUI.validate();

Thread thread = new Thread(new Runnable() {
try {
System.out.println("timer started");
Thread.sleep(5000);
System.out.println("timer done");
} catch(InterruptedException e) {
}
System.exit(0);
});
thread.start();
}

编辑:让我们“更深入”一点(这是我对 Swing/AWT 工作的看法)。
我想“请稍等”(见评论)应该显示在 CheckingMessagesGUI 类中,但实际上没有。
这与 GUI 的工作方式有关。如果您调用相应的 (Swing) 方法(draw、setText、setLocation,...),它不会直接更改显示上的任何内容;它只是在事件队列中对事件进行排队。事件调度线程是(应该是)唯一读取此队列并处理事件的线程。只要它被阻塞——在这种情况下被 sleep 阻塞——就不会显示对 GUI 的更改。 GUI 已卡住。

编辑2:
invokeLater Runnable被追加到队列的末尾,在处理完所有未决事件后由EDT稍后执行,invokeLater调用后的下一个命令将被执行.
invokeAndWait 与上面相同,但实际的 Thread 会阻塞,直到 EDT 执行 Runnable(在未决事件之后),也就是说,invokeAndWait 之后的命令只会在提交的 Runnable 执行后才开始。

关于java - 为什么 InvokeLater 导致我的 JFrame 无法正确显示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1843677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com