В Swing вы можете опубликовать событие в верхней части очереди событий EDT? - PullRequest
3 голосов
/ 30 июня 2011

Я ищу способ сделать то, что делает функция InvokeLater (), только вместо того, чтобы помещать событие в конец очереди, в которую оно помещается.По крайней мере, я думаю, что будет делать то, что я хочу, может быть, есть лучший способ.Ниже описывается то, что я пытаюсь воспроизвести.

Несколько лет назад я использовал каркас c ++ на Mac, в котором была функция, позволяющая добавлять объект Chore в список CriticalChore при обработке текущего события.Это можно сделать во время выполнения кода, равного Swings EDT.После завершения обработки текущего события и непосредственно перед вызовом GetNextEvent () платформа проверит, был ли список CriticalChore пустым.Если бы в списке были элементы, то была бы вызвана функция Perform () (т.е. run ()).Когда закончите со списком, все элементы будут удалены.

Эта функция оказалась очень полезной.Много раз, обрабатывая событие на ранней стадии, вы знаете, что вам нужно выполнить какой-то дополнительный код, но только после обработки большого количества другого кода.Но самое главное, нужно ли обрабатывать этот код перед обработкой любых других событий из очереди EDT.

Ответы [ 2 ]

1 голос
/ 30 июня 2011

Во-первых, как это делается

Можно установить глобальный прослушиватель со своей собственной очередью и по одному событию, опрашивающему очередь.Toolkit.addAWTEventListener(listener, eventMask)

Существует sun.awt.PeerEvent (для солнечного упоминания), который имеет ultimate priority, который предлагает простейшее значение, поскольку он практически такой же, как EventQueue.invokeLater, расширяющий java.awt.event.InvocationEvent, но, опять же, он не является стандартным.

Последнее: вот как это делается стандартным способом, я не проверял код, хотя (ленивый и очень поздний)

  class EventQueueX extends EventQueue{
        final ConcurrentLinkedQueue<AWTEvent> que=new ConcurrentLinkedQueue<AWTEvent>();

        @Override
        public AWTEvent getNextEvent() throws InterruptedException {
            AWTEvent e = que.poll();
            if (e!=null)
                return e;
            return super.getNextEvent();
        }
        @Override
        public synchronized AWTEvent peekEvent() {
            AWTEvent e = que.peek();
            if (e!=null)
                return e;
            return super.peekEvent();
        }

        public void pushFirst(AWTEvent e){
            que.offer(e);
            synchronized (this) {
                    notify();
                }
        }
        public void install(Toolkit toolkit){
            EventQueue q = toolkit.getSystemEventQueue();           
            if (q!=this)
                q.push(this);
        }
    };

Используйте EventQueueX.install(), а затем pushFirst(e), когда выхотите событие, и все готово.К сожалению, очередь будет деинсталлирована при исключении и может быть также удалена.

Далее, почему это плохо К вопросу.поместить событие в начало очереди - плохая идея.Если позже вам придется вызывать какой-либо код, просто структурировать свой собственный дизайн и в конце функции вызвать необходимый код, используйте очередь, если вам это необходимо.

Добавление дополнительного уровня супер-конечного приоритета может выглядетьХорошо, но это трудно понять концепцию дизайна для любого обычного разработчика AWT / Swing (в основном пользовательского интерфейса).Если вам нужно ставить в очередь действия, используйте свою собственную мини-среду без путаницы с awt.В то время как я особенно хорош в хакерстве, даже сам, я бы подстроил такой подход (мягко говоря).

1 голос
/ 30 июня 2011

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

Я думаю, что лучший ответ - вообще не делать этого. Если у вас есть необходимость, дизайн, вероятно, необходимо переработать. Предполагается, что EventDispatchThread предназначен только для очень коротких действий, поскольку никогда не должен выглядеть для конечного пользователя так, как будто приложение зависло. Из-за этого очередь для EDT всегда должна быть достаточно короткой, чтобы все, что вы на нее надевали, происходило «мгновенно» с точки зрения пользователя, поэтому все, что на ней находится, должно иметь «мгновенный» приоритет.

Если нужно что-то сделать, что не является кратковременным действием, для этого есть отдельная методология. Для этого есть класс Swing Worker , и вы должны использовать его для настройки задач, которые выполняются вместе с EDT, и прослушивать их ответы.

Вот учебник Swing Worker . Есть и некоторые другие хорошие предложения, которые Google использует с помощью запроса «Учебник по Java SwingWorker».

...