Java使GUI等待计时器 [英] Java make GUI wait for a timer

查看:115
本文介绍了Java使GUI等待计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是希望这个程序等待计时器。我只想让程序暂停两秒钟。我希望这个程序做的是显示开始,等待两秒钟直到计时器结束,然后显示开始,完成等待,完成。如何让这个程序等待计时器完成?我相信它当前在一个单独的线程中创建了计时器,而不是暂停主线程,因此它显示Start,Finished然后等待两秒钟,然后显示Start,Finished,Finished Waiting。这不是我希望事情发生的顺序,我在运行GUI时找到了一个简单的计时器示例并且没有找到。感谢您的帮助,以下是代码:

I simply want this program to wait for a timer. All I want is for the program to pause for two seconds. I want this program to do is display "Start," wait for two seconds until the timer has finished, then display "Start, Finished Waiting, Finished." How can I make this program wait for the timer to finish? I believe that it currently creates the timer in a separate thread, not pausing the main thread, so it displays,"Start, Finished" then waits for two seconds and then displays "Start, Finished, Finished Waiting." This is not the order that I want things to happen in, and I have looked all over for a simple timer example when running a GUI and have found none. Thank you for your help, here is the code:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.Timer;

public class GUI extends JFrame {

    private static final long serialVersionUID = 3560258176733156660L;

    public static void main(String[] args) {
        new GUI().setVisible(true);
    }

    private Timer timer;
    private JTextArea area;
    private String text;

    public GUI() {
        setLayout(null);
        setSize(500, 120);
        setTitle("Timer");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        text = "";
        area = new JTextArea(text);
        area.setBounds(0, 0, 500, 120);
        add(area);
        doThings();

    }
    public void doThings() {
        text += "Start, ";
        area.setText(text);
        // Want program to wait for two seconds
        waitForTwoSeconds();
        text += "Finished ";
        area.setText(text);

    }
    public void waitForTwoSeconds() {

        timer = new Timer(2000, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                text += "Finished Waiting, ";
                area.setText(text);
                timer.stop();
            }
        });
        timer.start();
    }

}


推荐答案

在您调用 waitForTwoSeconds 之后从代码中取出代码并放入 actionPerformed 方法...

Take the code from after you call waitForTwoSeconds and place within the actionPerformed method...

public void doThings() {
    area.setText("Start, ");
    // Want program to wait for two seconds
    waitForTwoSeconds();

}

public void waitForTwoSeconds() {

    timer = new Timer(2000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            area.append("Finished Waiting, ");
            area.append("Finished ");
            timer.stop();
        }
    });
    timer.setRepeats(false);
    timer.start();
}

这将导致已完成等待,已完成在你点击按钮后2秒后附加到 JTextArea ...

This will cause Finished Waiting, Finished to be append to the JTextArea 2 seconds after you click the button...

你做不想在事件调度线程的上下文中执行任何长时间运行/阻塞操作,这将使它看起来像你的程序挂起,因为它有。

You DO NOT want to perform any long running/blocking operations within the context of the Event Dispatching Thread, this WILL make it look like your program as hang, cause it has.

参见, Swing中的并发如何使用Swing Timers 获取更多详细信息

See, Concurrency in Swing and How to use Swing Timers for more details

更新...

Swing(和大多数用户界面)是事件驱动的,也就是说,某些事情会发生并且您会对其做出响应。例如,使用计时器,计时器跳闸并且您响应了该事件。你无法阻止/等待事件调度线程,它只会导致UI停止响应和绘画,这是框架的工作方式,你可以学会忍受它或继续被它挫败(记住,想要什么,让它工作,是两件不同的事情)

Swing (and most UIs) are event driven, that is, something happens and you respond to it. For instance, with the Timer, the timer tripped and you responded to the event. You can't block/wait within the Event Dispatching Thread, it will simply cause the UI to stop responding and painting, this is the way the framework works, you can learn to live with it or continue to be frustrated by it (remember, wanting something and getting it to work, are two different things)

然而,你可以做的事情,计时器是一个例子,另一个是 SwingWorker

There are, however, things you can do, the Timer is one example, another is the SwingWorker

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextArea ta;

        public TestPane() {
            setLayout(new BorderLayout());
            ta = new JTextArea(10, 20);
            JButton btn = new JButton("Make it so");
            add(new JScrollPane(ta));
            add(btn, BorderLayout.SOUTH);

            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btn.setEnabled(false);
                    ta.append("Start, ");
                    SwingWorker<String, String> worker = new SwingWorker<String, String>() {

                        @Override
                        protected String doInBackground() throws Exception {
                            Thread.sleep(2000);
                            publish("Finished waiting, ");
                            return null;
                        }

                        @Override
                        protected void process(List<String> chunks) {
                            for (String text : chunks) {
                                ta.append(text);
                            }
                        }

                        @Override
                        protected void done() {
                            ta.append("Finished");
                            btn.setEnabled(true);
                        }

                    };
                    worker.execute();
                }
            });
        }

    }

}

这基本上是做什么的,在后台线程中,它等待两秒然后(通过发布 / 进程方法),打印完成等待,然后在 doInBackground 返回后,完成被(最终)调用并且完成打印。

What this basically does is, in a background thread, it waits two seconds and then (via the publish/process methods), prints "Finished Waiting", then after the doInBackground returns, done is (eventually) called and "Finished" is printed.

这一切都已完成,因此UI更新发生在Event Dispatching Thread的上下文中,满足Swing的单线程要求

This is all done so that the UI updates occur from within the context of the Event Dispatching Thread, meeting the single thread requirements of Swing

这篇关于Java使GUI等待计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆