在 Java 中创建一个几秒钟后消失的简单消息框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5966005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 13:43:56  来源:igfitidea点击:

Create a plain message box that disappears after a few seconds in Java

javaswing

提问by skyork

I wonder what is the best approach to make a JOptionPane style plain message box disappear after being displayed for a set amount of seconds.

我想知道让 JOptionPane 样式的纯消息框在显示一定秒数后消失的最佳方法是什么。

I am thinking to fire up a separate thread (which uses a timer) from the main GUI thread to do this, so that the main GUI can carry on processing other events etc. But how do I actually make the message box in this separate thread disappear and terminate the thread properly. Thanks.

我正在考虑从主 GUI 线程启动一个单独的线程(它使用计时器)来执行此操作,以便主 GUI 可以继续处理其他事件等。但是我如何在这个单独的线程中实际制作消息框消失并正确终止线程。谢谢。

Edit: so this is what I come up with by following the solutions posted below

编辑:所以这就是我按照下面发布的解决方案提出的

package util;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Timer;

public class DisappearingMessage implements ActionListener
{
    private final int ONE_SECOND = 1000;

    private Timer timer;
    private JFrame frame;
    private JLabel msgLabel;

public DisappearingMessage (String str, int seconds) 
{
frame = new JFrame ("Test Message");
msgLabel = new JLabel (str, SwingConstants.CENTER);
msgLabel.setPreferredSize(new Dimension(600, 400));

timer = new Timer (this.ONE_SECOND * seconds, this);
// only need to fire up once to make the message box disappear
timer.setRepeats(false);
}

/**
 * Start the timer
 */
public void start ()
{
// make the message box appear and start the timer
frame.getContentPane().add(msgLabel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null); 
frame.setVisible(true);

timer.start();
}

/**
 * Handling the event fired by the timer
 */
public void actionPerformed (ActionEvent event)
{
// stop the timer and kill the message box
timer.stop();
frame.dispose();
}

public static void main (String[] args)
{
DisappearingMessage dm = new DisappearingMessage("Test", 5);
dm.start();
}
}

Now the question is that, as i cam going to create multiple instances of this class throughout the course of the interaction between the user and the main GUI, I wonder whether the dispose() method cleans up everything properly every time. Otherwise, I may end up with accumulating lots of redundant objects in memory. thanks.

现在的问题是,由于我将在用户和主 GUI 之间的整个交互过程中创建此类的多个实例,我想知道 dispose() 方法是否每次都正确清理所有内容。否则,我最终可能会在内存中积累大量冗余对象。谢谢。

采纳答案by jfpoilpret

I think in your situation, you can't use any of JOptionPanestatic methods (showX...). You have to create a JOptionPaneinstance instead, then create a JDialogfrom it and show that JDialogyourself. Once you have JDialog, you can force its visibility.

我认为在您的情况下,您不能使用任何JOptionPane静态方法 ( showX...)。您必须创建一个JOptionPane实例,然后从中创建一个实例JDialogJDialog自己展示。一旦你有了JDialog,你就可以强制它的可见性。

// Replace JOptionPane.showXxxx(args) with new JOptionPane(args)
JOptionPane pane = new JOptionPane(...);
final JDialog dialog = pane.createDialog("title");
Timer timer = new Timer(DELAY, new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        dialog.setVisible(false);
        // or maybe you'll need dialog.dispose() instead?
    }
});
timer.setRepeats(false);
timer.start();
dialog.setVisible(true);

I haven't tried it so I can't guarantee that it works but I think it should ;-)

我没有尝试过,所以我不能保证它有效,但我认为它应该;-)

Of course, here Timeris javax.swing.Timer, as someone else already mentioned, thus you're sure the action will run in the EDT and you won't have any problem with creating or terminating your own Thread.

当然,这里Timerjavax.swing.Timer,正如其他人已经提到的那样,因此您确定该操作将在 EDT 中运行,并且您在创建或终止您自己的Thread.

回答by wds

Timershave their own threads. I think what you probably should do is create a new Timer(or, preferably, make one that you reuse till you don't need it any more), schedule a task that will ask for the message box to disappear and then have that task add another task to the event queue, which will remove the message box.

定时器有自己的线程。我认为您可能应该做的是创建一个新的Timer(或者,最好制作一个您可以重复使用直到您不再需要它),安排一个任务,该任务将要求消息框消失,然后添加该任务另一个任务到事件队列,这将删除消息框。

There might be a better way though.

不过可能有更好的方法。

In addition: Yes, using javax.swing.timerwould probably be better. The reason I talk about using two tasks in the above is that I assume you will have to execute your hiding method inside of the AWT thread to avoid certain subtle race issues that might arise. If you use javax.swing.Timeryou're already executing in the AWT thread, so that point becomes moot.

另外:是的,使用javax.swing.timer可能会更好。我在上面谈到使用两个任务的原因是我假设您必须在 AWT 线程内执行隐藏方法以避免可能出现的某些微妙的竞争问题。如果您使用,javax.swing.Timer您已经在 AWT 线程中执行,所以这一点变得没有实际意义。