Как реализовать простую задачу в Java Swing

У меня есть приложение с графическим интерфейсом, которое становится довольно медленным. Я хочу начать вводить синхронизацию для различных задач с графическим интерфейсом - однако многие из наших действий с графическим интерфейсом запускают другие действия, которые затем "вызывают позже". инициировать другие действия.

В конце концов, все успокаивается, и больше нечего делать. В настоящее время я хочу остановить таймер и сообщить, как долго этот GUI & quot; action & quot; взял.

Я решил, что способ сделать это, чтобы реализовать метод под названиемinvokeOnceIdle(Runnable task), Метод выполнит поставленную задачу только после того, как AWTEventQueue станет "пустым". то есть поставляемая «задача»; должно быть последним в очереди.

Один из способов сделать это состоит в том, если существует способ указать «низший» уровень. приоритетSwingUtilities.invokeLater - но это невозможно.

Затем я посмотрел, смогу ли я «invokeLater» quot; Runnable, который проверяет, является ли очередь событий «пустой» - но публичного способа увидеть, является ли очередь событий фактически пустой, нет.

Какой лучший способ сделать это?

Ответы на вопрос(2)

isEventDispatchThread возвращает, если текущийAWTEventQueue пусто или нет,

if is current AWTEventQueue is empty you can to post a new event(s) to EventQueue from

invokeAndWait() а такжеinvokeLater тоже

if is current AWTEventQueue is not empty then you can not to use invokeAndWait() only 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;
    }
}
 Paul Hollingsworth26 июн. 2012 г., 11:59
Я не понимаю ваш пример - даже если есть несколько очередей событий AWT, я все еще не вижу, как это поможет мне определить, является ли какая-либо из них «пустой».
 Paul Hollingsworth26 июн. 2012 г., 11:50
Я думал, isDispatchThread просто скажет мне, является ли текущий поток потоком Event Dispatch. Но я уже знаю, что это так. Весь код выполняется в потоке AWT - в нашем коде нет других потоков. Мне нужно знать, есть ли другие задачи очереди событий AWT, ожидающие выполнения после текущей задачи ...
 26 июн. 2012 г., 11:52
До Java7 есть только один EDT, вы не можете быть в состоянии умножить EDT, и EDT имеет два состояния, как вы можете видеть из моего примера кода
Решение Вопроса

Используя собственную очередь событий, вы можете легко достичь этой цели. Вот кое-что, что я приготовил и должен помочь вам:

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()

 26 июн. 2012 г., 12:50
@GuillaumePolet, то вы можете увидеть разницу модели против. Представление, результат - Index / ArrayXxxExceptions, в случае, если контекст также отображается с исключениями RepaintManager,
 26 июн. 2012 г., 12:24
@PaulHollingsworth Как правило, что ваша & quot; очередь событий пуста & quot; условие переводится вEventQueue.peekEvent() == null
 26 июн. 2012 г., 12:28
это не гарантирует, что все события из модели выполняются в представлении, clear () & amp; push () может быть полезен после re_build GUI (модель и представление) после исключений из RepaintManager, точка ...
 Paul Hollingsworth26 июн. 2012 г., 12:19
Я еще не пробовал, но думаю, что это сработает. Спасибо!
 26 июн. 2012 г., 12:34
@GuillaumePolet: это классMyEventQueue внутренний класс?

Ваш ответ на вопрос