睡眠导致具有不可见内容的框架[重复]

Posted

技术标签:

【中文标题】睡眠导致具有不可见内容的框架[重复]【英文标题】:Sleep causing frame with invisible content [duplicate] 【发布时间】:2018-02-01 19:39:08 【问题描述】:

我有一个带有菜单栏菜单的框架,当我选择一个菜单项时,我希望程序显示一条消息,然后几秒钟后(通过睡眠功能)自动关闭此消息。

但我得到的不是这个,而是空消息(带有不可见内容的 jdialog):

如果删除关闭消息,它的内容会在休眠时间后出现。

我需要改变什么才能得到正确的结果?

我想得到这个:

完整的工作代码:

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.util.concurrent.TimeUnit;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;

public class MessageSleepTest extends JDialog 

    public static void main(String[] args) 

        SwingUtilities.invokeLater(new Runnable()
            public void run()
                new Frame("frame with menubar");
            
        );
    


class Message extends JDialog 

    public Message() 
        this.setLayout(new GridLayout(0, 1));
        this.add(new JLabel("Displaying this message for 3 seconds and then closing it...", JLabel.CENTER));

        this.setAlwaysOnTop(true);
        this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    


class Frame extends JFrame

    public Frame(String title)

        super(title);
        setJMenuBar(new MenuBar());
        setPreferredSize(new Dimension(500, 300));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setLocationRelativeTo(null); // center the frame
        setVisible(true);

    



class MenuBar extends JMenuBar implements ActionListener
    public static JMenuItem itmOpen;

    public MenuBar() 
        JMenu menuFile = new JMenu("File");

        itmOpen = new JMenuItem("Open...");
        itmOpen.addActionListener(this);

        add(menuFile);
        menuFile.add(itmOpen);
    

    @Override
    public void actionPerformed(ActionEvent e) 
        JMenuItem source = (JMenuItem)e.getSource();

        if(source == itmOpen)

            JDialog message = new Message();
            try 
                TimeUnit.SECONDS.sleep(3);
             catch (InterruptedException ex) 
                ex.printStackTrace();
            
            WindowEvent windowClosing = new WindowEvent(message, WindowEvent.WINDOW_CLOSING);
            message.dispatchEvent(windowClosing);

        
    

【问题讨论】:

【参考方案1】:

你有一个线程问题:sleep 是在 AWT 的 Event Dispatch Thread 上执行的,它在 AWT 和 Swing 中完成所有的事件处理工作。因此,当您单击菜单项时,它会为Message 创建对象,但会被setVisible() 方法卡住,该方法通常会向JDialog 发送一个事件以进行布局和显示。此消息进入 EDT 的队列,在您的事件处理程序(actionPerformed 方法)完成后,它会得到处理。然而睡眠介于两者之间。

所以试试这样的:

@Override
public void actionPerformed(ActionEvent e) 
   JMenuItem source = (JMenuItem) e.getSource();
   if (source == itmOpen) 
      final JDialog message = new Message();
      new Thread( new Runnable() 
         @Override
         public void run() 
            try 
               TimeUnit.SECONDS.sleep(3);
             catch (InterruptedException ex) 
               // Do nothing with it
            
            WindowEvent windowClosing = new WindowEvent(message, WindowEvent.WINDOW_CLOSING);
            message.dispatchEvent(windowClosing);
         
      ).start();
   

【讨论】:

非常感谢您的解释!你的方法奏效了。【参考方案2】:

使用 swing.Timer 的另一种解决方案

@Override
public void actionPerformed(ActionEvent e) 
    JMenuItem source = (JMenuItem)e.getSource();

    if(source == itmOpen)

        JDialog message = new Message();
        Timer timer = new Timer(1000 * 3, new ActionListener() 
            public void actionPerformed(ActionEvent e) 
                WindowEvent windowClosing = new WindowEvent(message, WindowEvent.WINDOW_CLOSING);
                message.dispatchEvent(windowClosing);
            
        );
        timer.setRepeats(false);
        timer.start();

    

【讨论】:

以上是关于睡眠导致具有不可见内容的框架[重复]的主要内容,如果未能解决你的问题,请参考以下文章

java swing问题:JFrame根面板不透明且可见,内容面板不透明且可见,层面板透明且可见,

在响应框中制作响应图像而不会导致页面速度出现可见内容问题

表视图不可见

如何在 Paraview 中打开具有可见内容的 .pvd 文件?

使用 jquery 更改具有嵌套内容的 div 的可见性,onclick

MKMapView 缩放以显示框架中的所有注释