Kilka razy przeczytałem określony tutorial na temat key bindings, ale pamięć podręczna mojego mózgu nie wydaje się wystarczająco duża, aby pomieścić skomplikowane procesy.W jaki sposób Java wysyła KeyEvents?
byłem debugowania Kluczowym problemem wiązania (okazało się, używałem złego JComponent.WHEN_*
warunek), i natknąłem się na zwięzły i wesołym javadoc dla pakietu prywatnej javax.swing.KeyboardManager
przez (niestety) inżynier anonimowy Java.
Moje pytanie brzmi następująco: z wyjątkiem KeyEventDispatcher
, które jest sprawdzane na samym początku, czy w opisie brakuje czegoś i/lub coś pomyłkowo?
Klasa KeyboardManager służy do pomocy działań wysyłka klawiaturowych dla WHEN_IN_FOCUSED_WINDOW actions stylu. Akcje z innymi warunkami są obsługiwane bezpośrednio w JComponent.
Oto opis symantics [sic], w jaki klawiatura wysyłki powinien pracować conajmniej [sic!], Jak ja go rozumiem.
KeyEvents są wysyłane do komponentu fokusowanego . Menedżer focusów dostaje pierwsze pęknięcie podczas przetwarzania tego zdarzenia . Jeśli menedżer fokusowania nie chce tego, wówczas JComponent wywołuje super.processKeyEvent(), co umożliwia słuchaczom przetworzenie zdarzenia .
Jeśli żaden ze słuchaczy nie "zużyje" zdarzenia, to klawisze dostaną strzał . Tutaj zaczynają się interesować rzeczy zaczynające się od . Po pierwsze, KeyStokes [sic] zdefiniowane za pomocą warunku WHEN_FOCUSED mają szansę. Jeśli żaden z nich nie chce tego zdarzenia, komponent przechodzi, chociaż jego rodzice przeglądali akcje typu WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.
Jeśli nikt jeszcze go nie zajął, oznacza to, że podciąga się tutaj . Następnie wyszukujemy komponenty zarejestrowane dla zdarzeń WHEN_IN_FOCUSED_WINDOW i wywołujemy dla nich . Zauważ, że jeśli nie znajdziemy żadnego z tych , przekazujemy to wydarzenie na w paskach i niech mają na sobie pęknięcie . Są traktowane inaczej.
Na koniec sprawdzamy, czy patrzymy na wewnętrzną ramkę . Jeśli jesteśmy i nie ma potrzeby, aby wydarzenie miało miejsce, wówczas podnosimy się do twórcy InternalFrame i widzimy , jeśli ktoś chce tego zdarzenia (i tak dalej: itd.).
(AKTUALIZACJA) Jeśli kiedykolwiek zastanawialiście się o tym śmiałym ostrzeżenia w klawiszy przewodniku:
Ponieważ kolejność przeszukiwania elementów jest nieprzewidywalny, uniknąć powielania WHEN_IN_FOCUSED_WINDOW wiązania!
To z powodu tego segmentu w KeyboardManager#fireKeyboardAction
:
Object tmp = keyMap.get(ks);
if (tmp == null) {
// don't do anything
} else if (tmp instanceof JComponent) {
...
} else if (tmp instanceof Vector) { //more than one comp registered for this
Vector v = (Vector)tmp;
// There is no well defined order for WHEN_IN_FOCUSED_WINDOW
// bindings, but we give precedence to those bindings just
// added. This is done so that JMenus WHEN_IN_FOCUSED_WINDOW
// bindings are accessed before those of the JRootPane (they
// both have a WHEN_IN_FOCUSED_WINDOW binding for enter).
for (int counter = v.size() - 1; counter >= 0; counter--) {
JComponent c = (JComponent)v.elementAt(counter);
//System.out.println("Trying collision: " + c + " vector = "+ v.size());
if (c.isShowing() && c.isEnabled()) { // don't want to give these out
fireBinding(c, ks, e, pressed);
if (e.isConsumed())
return true;
}
}
Więc kolejność przeszukiwania jest faktycznie przewidywalne, ale oczywiście zależy od tej konkretnej implementacji, więc lepiej nie polegać na to w ogóle. Niech to będzie nieprzewidywalne.
(Javadoc i kod jest od jdk1.6.0_b105 na WinXP).
To jest miła analiza obsługi KeyEvent ... ale nie wiem, czy to właściwie pytanie, na które można odpowiedzieć. – BoffinbraiN
@BoffinbraiN: Miałem nadzieję, że ktoś z kilkoma huśtawkowymi znaczkami mówi coś w stylu "według mojej najlepszej wiedzy" :) –
Tak, zdecydowanie byłoby lepiej! Ale myślę, że w przypadku czegoś tak głębokiego, to naprawdę jest specyficzne dla implementacji, i przeanalizowałeś tę implementację znacznie ostrożniej niż najdrożsi programiści. ;) Najlepiej nie uzależniać kodu od tych szczegółów. – BoffinbraiN