如何实现的Java Swing空闲任务(How to implement idle task in

2019-06-25 18:56发布

我有一个越来越是相当慢的一个GUI应用程序。 我要开始为各种GUI任务的引入时机 - 然而,我们的许多GUI操作的触发,然后“后来援引”触发其他动作的其他行动。

最终,这一切平息下来,并没有什么更多的事情要做。 在这个时候,我想停止计时,并报告了多久即GUI“行动”了。

我想做到这一点的办法是实现一个名为方法invokeOnceIdle(Runnable task) 。 该方法将执行任务提供唯一的一次AWTEventQueue是“空”。 即所提供的“任务”应该是在队列中的最后一件事。

这样做将是一个办法是,如果有指定一个“最低”优先的方式SwingUtilities.invokeLater -但这是不可能的。

我旁边看了看,如果我能“的invokeLater”一个Runnable进行检查,看是否该事件队列是“空” - 但有看,如果事件队列就是空不公开的方式。

什么是做到这一点的最好方法是什么?

Answer 1:

使用你自己的事件队列,你可以很容易地实现这个目标。 这里的东西,我做起来,应该让你去:

private static class MyEventQueue extends EventQueue {

    private Deque<Runnable> onceIdle = new LinkedList<Runnable>();

    public MyEventQueue() {
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(this);
    }

    public void runOnceIdle(Runnable toRun) {
        onceIdle.addLast(toRun);
    }

    @Override
    protected void dispatchEvent(AWTEvent event) {
        super.dispatchEvent(event);
        if (peekEvent() == null) {
            for (Runnable toRun : onceIdle) {
                toRun.run();
            }
            onceIdle.clear();
        }
    }
}

所有你需要做的就是把你的“一旦闲置”可运行使用的EventQueue实例runOnceIdle()



Answer 2:

isEventDispatchThread返回如果是当前AWTEventQueue为空,

  • 如果是当前AWTEventQueue是空的,你可以到一个新的事件(或多个)从发布到EventQueue中

invokeAndWait()invokeLater

  • 如果是当前AWTEventQueue不是空的,那么你可以不使用invokeAndWait()唯一invokeLater()

例如

import java.awt.EventQueue;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class IsThereEDT {

    private ScheduledExecutorService scheduler;
    private AccurateScheduledRunnable periodic;
    private ScheduledFuture<?> periodicMonitor;
    private int taskPeriod = 30;
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    private Date dateRun;
    private JFrame frame1 = new JFrame("Frame 1");

    public IsThereEDT() {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        periodic = new AccurateScheduledRunnable() {

            private final int ALLOWED_TARDINESS = 200;
            private int countRun = 0;
            private int countCalled = 0;
            private int maxCalled = 10;

            @Override
            public void run() {
                countCalled++;
                if (countCalled < maxCalled) {
                    if (countCalled % 3 == 0) {
                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                System.out.println("Push a new event to EDT");
                                frame1.repaint();
                                isThereReallyEDT();
                            }
                        });
                    } else {
                        if (this.getExecutionTime() < ALLOWED_TARDINESS) {
                            countRun++;
                            isThereReallyEDT(); // non on EDT
                        }
                    }
                } else {
                    System.out.println("Terminating this madness");
                    System.exit(0);
                }
            }
        };
        periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
        periodic.setThreadMonitor(periodicMonitor);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                isThereReallyEDT();
                frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame1.getContentPane().add(new JLabel("Hello in frame 1"));
                frame1.pack();
                frame1.setLocation(100, 100);
                frame1.setVisible(true);
            }
        });
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame2 = new JFrame("Frame 2");
                frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame2.getContentPane().add(new JLabel("Hello in frame 2"));
                frame2.pack();
                frame2.setLocation(200, 200);
                frame2.setVisible(true);
                isThereReallyEDT();
            }
        });
    }

    private void isThereReallyEDT() {
        dateRun = new java.util.Date();
        System.out.println("                         Time at : " + sdf.format(dateRun));
        if (EventQueue.isDispatchThread()) {
            System.out.println("EventQueue.isDispatchThread");
        } else {
            System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
        }
        if (SwingUtilities.isEventDispatchThread()) {
            System.out.println("SwingUtilities.isEventDispatchThread");
        } else {
            System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        IsThereEDT isdt = new IsThereEDT();
    }
}

abstract class AccurateScheduledRunnable implements Runnable {

    private ScheduledFuture<?> thisThreadsMonitor;

    public void setThreadMonitor(ScheduledFuture<?> monitor) {
        this.thisThreadsMonitor = monitor;
    }

    protected long getExecutionTime() {
        long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
        return delay;
    }
}


文章来源: How to implement idle task in Java Swing