简体   繁体   English

JWindow从while循环返回之前,JWindow不会重新绘制

[英]JWindow not repainting until JFrame returns from while loop

Assume I have a JWindow and a JFrame called TestWindow and TestFrame which should both be shown at the same time, why does the TestWindow only draw a blank grey window without its label while the TestFrame is inside the while(true)??? 假定我有一个JWindow和一个分别称为TestWindow和TestFrame的JFrame,它们应同时显示,为什么TestWindow在while(true)内时只绘制空白的灰色窗口而没有其标签?

And why if I remove the while(true) the TestWindow correctly shows? 为什么我删除了TestWindow正确显示的while(true)?

This is as example of a more complex program where I need to show a splashscreen while the main application is starting which takes 1 or 2 seconds. 这是一个更复杂的程序的示例,在该程序中,我需要在主应用程序启动时显示启动画面,这需要1或2秒钟。 During this time the splashscreen should be shown regardless of the state of the main application, instead the splashscreen shows only when the main application is already finished, invokeAndWait doesn't actually wait for the splashscreen to be initialized. 在此期间,无论主应用程序处于什么状态,都应显示初始屏幕,而初始屏幕仅在主应用程序已完成时才显示,invokeAndWait实际上并不等待初始屏幕初始化。

TestFrame.java : TestFrame.java

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class TestFrame extends JFrame
{
    public static void main(String args[])
    {
        try
        {
           SwingUtilities.invokeAndWait(new Runnable()
           {
               @Override
               public void run()
               {
                   new TestWindow();
               }
           });
        }
        catch (Exception ex)
       {
           Logger.getLogger(TestFrame.class.getName()).log(Level.SEVERE, null, ex);
       }
       SwingUtilities.invokeLater(new Runnable()
       {
           @Override
           public void run()
           {
               new TestFrame();
           }
        });
    }

    public TestFrame()
    {
        super("TestFrame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(new JLabel("sss"), BorderLayout.CENTER);
        setSize(500, 120);
        setVisible(true);
        while(true)
        {
            //this makes the other not show
        }
    }
}

TestWindow.java : TestWindow.java

import java.awt.BorderLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;

public class TestWindow
{
    public TestWindow()
    {
        JWindow jWindow = new JWindow();
        JPanel contentPanel = new JPanel();
        final JLabel label = new JLabel("Test Window");
        contentPanel.add(label, BorderLayout.CENTER);
        jWindow.add(contentPanel);
        jWindow.setSize(300, 200);
        jWindow.setAlwaysOnTop(true);
        jWindow.setVisible(true);
    }
}

EDIT : 编辑

By the way, I realized putting a 顺便说一句,我意识到

catch (Exception ex)
        {
            Logger.getLogger(TestFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        try
        {
            Thread.sleep(1000);
        }

between the two TestWindow and TestFrame creation actually solves the problem, isn't there anything less hacky than this??? 在两个TestWindow和TestFrame创建之间可以真正解决问题,难道没有比这更hacky的了吗???

Your while (true) loop is being called on the Swing event dispatch thread, or EDT, tying it up and preventing this thread from doing its necessary actions including drawing all your GUI's and interacting with the user. 您的while (true)循环在Swing事件分配线程或EDT上被调用,将其绑定并阻止该线程执行其必要的操作,包括绘制所有GUI并与用户进行交互。 The solution is simple -- 1) get rid of the while loop (as you already figured out), or 2) if the loop is absolutely necessary, do it in a background thread. 解决方案很简单-1)摆脱while循环(您已经弄清楚了),或2)如果绝对需要循环,请在后台线程中执行。

For more details on Swing threading, please check out Lesson: Concurrency in Swing . 有关Swing线程的更多详细信息,请参阅课程:Swing中的并发

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM