Как генерируются события в Java?



Во-первых, я не спрашиваю о событии Обработка. Я знаю, что обработка реализуется с помощью шаблона наблюдателя.



Позвольте мне привести небольшой пример. Предположим, у меня есть кнопка J на JFrame. Я нажимаю на верхнюю часть этой кнопки.
Теперь, как кнопка узнает, что я нажал на нее?

1) Есть ли какой-либо поток java, ожидающий щелчка? Если да, то откуда взялся этот код (подождите, пока я не нажму часть)? Затем делает каждый и каждый качели компонент ждет событий на вершине из нитей? Я предполагаю, что это очень дорогая задача.



2) Если нет, то как это работает?
467   3  

3 ответов:

Шаблон наблюдателя используется во всем стеке:

  1. пользователь отпускает кнопку мыши
  2. мышь посылает сообщение в процессор, который запускает аппаратное прерывание
  3. Обработчик прерываний операционной системы понимает, что мышь не была перемещена с момента нажатия кнопки, т. е. что произошел щелчок мыши. Он идентифицирует окно в положении мыши и приложение, ответственное за это окно, и помещает сообщение, нажатое мышью, в окно. очередь событий приложения
  4. "поток отправки событий" нашего приложения Swing выполняет цикл вида:

    while (!shutdownRequested) {
        Event e = retrieveEventFromEventQueue(); // for instance our mouse clicked event
        handleEvent(e);
    }
    

    В AWT / Swing есть один поток, выполняющий этот код. Первый вызов будет блокироваться до тех пор, пока не появится новое событие, и handleEvent() вызовет слушателей для этого события. То есть один поток выполняет все обновления пользовательского интерфейса (именно поэтому длительные задачи не должны выполняться в прослушивателях событий, так как это замораживает пользовательский интерфейс) и спит, если пользователь этого не делает взаимодействуйте с приложением.

Есть ли какой-либо поток java, ожидающий щелчка?

Да, java.awt.EventDispatchThread. Вот цитата из раздела потока отправки событий учебника java:

Код обработки событий Swing выполняется в специальном потоке, известном как событие диспетчеризируют поток. Большинство кода, который вызывает методы качания и работает на эта тема. Это необходимо, потому что большинство методов Swing object не "потокобезопасно": вызов их из нескольких потоков рискует потоком помехи или ошибки согласованности памяти. Некоторые качели компонент методы помечены "потокобезопасными" в спецификации API; они могут безопасно вызываться из любого потока. Все другие методы компонента Swing должен быть вызван из потока отправки событий. Программы, которые игнорируют это правило может функционировать правильно большую часть времени, но подлежит непредсказуемые ошибки, которые трудно воспроизвести.

Чтобы ответить на ваш следующий вопрос,

Если да, то откуда приходит ли этот код из (подождите, пока я нажму часть)?

EventDispatchThread запускает постоянный событийный насос с вызовом pumpEvents(Conditional) в своем методе run.

public void run() {
    try {
        pumpEvents(new Conditional() {
            public boolean evaluate() {
                return true;
            }
        });
    } finally {
        getEventQueue().detachDispatchThread(this);
    }
}

Любой обработчик событий может в любое время заблокировать этот насос событий, но должен запустить новый насос (не новый EDT), снова вызвав pumpEvents(Conditional). Этот вторичный насос событий выйдет автоматически, как только Conditional оценит до false и дополнительный Event будет перекачан и отправлен.

Событие насоса вызовет AWTEvent#getNextEvent, который получит событие из очереди событий.

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

Опять же, учебник java отвечает на этот вопрос

Полезно подумать о коде, запущенном в потоке отправки событий как серия коротких заданий. Большинство задач-это призывы методы обработки событий, такие как ActionListener.действие выполнено. Другой задачи можно планировать с помощью кода приложения, используя invokeLater или invokeAndWait. Задачи в потоке отправки событий должны выполняться быстро; если они этого не делают, необработанные события возвращаются и пользовательский интерфейс становится неотзывчивый.

События помещаются в очередь в независимом от платформы классе java.awt.EventQueue. События хранятся в очереди с заданным приоритетом, для каждого приоритета создается одна очередь.
private static final int LOW_PRIORITY = 0;
private static final int NORM_PRIORITY = 1;
private static final int HIGH_PRIORITY = 2;
private static final int ULTIMATE_PRIORITY = 3;

События извлекаются из EventQueue, начиная с очереди самый высокий приоритет. Мы продвигаемся в порядке убывания по всем очередям.

Обратите внимание, что некоторые обычно вызываемые события кэшируются для повышения производительности, например PaintEvent.Paint, PaintEvent.UPDATE, MouseEvent.MOUSE_MOVED, MouveSevent.MOUSE_DRAGGED.

Это не так дорого, как вы думаете.

Есть ли какой-либо поток java, ожидающий щелчка?

Да, это называется потоком диспетчеризации событий (EDT).

Поскольку все компоненты в Swing являются легкими, то есть просто приятная анимация и ничего больше, это действительно компонент верхнего уровня, скажем, JFrame, который отслеживает щелчки мыши и передает их компоненту на этом пикселе.

Comments

    Ничего не найдено.