I've read the definite tutorial on key bindings a few times, but my brain cache doesn't seem large enough to hold the complicated processes.
I was debugging a key binding problem (turned out I was using the wrong JComponent.WHEN_* condition), and I stumbled upon a concise and hilarious javadoc for the package private javax.swing.KeyboardManager by an (unfortunately) anonymous Java engineer.
My question is this: except for KeyEventDispatcher which is checked at the very beginning, does the description miss and/or mistake anything?
The KeyboardManager class is used to
help dispatch keyboard actions for the
WHEN_IN_FOCUSED_WINDOW style actions.
Actions with other conditions are
handled directly in JComponent.
Here's a description of the symantics
[sic] of how keyboard dispatching
should work atleast [sic] as I
understand it.
KeyEvents are dispatched to the
focused component. The focus manager
gets first crack at processing this
event. If the focus manager doesn't
want it, then the JComponent calls
super.processKeyEvent() this allows
listeners a chance to process the
event.
If none of the listeners "consumes"
the event then the keybindings get a
shot. This is where things start to
get interesting. First, KeyStokes
[sic] defined with the WHEN_FOCUSED
condition get a chance. If none of
these want the event, then the
component walks though it's [sic] parents
looked for actions of type
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.
If no one has taken it yet, then it
winds up here. We then look for
components registered for
WHEN_IN_FOCUSED_WINDOW events and fire
to them. Note that if none of those
are found then we pass the event to
the menubars and let them have a crack
at it. They're handled differently.
Lastly, we check if we're looking at
an internal frame. If we are and no
one wanted the event then we move up
to the InternalFrame's creator and see
if anyone wants the event (and so on
and so on).
(UPDATE) If you've ever wondered about this bold warning in the key bindings guide:
Because the order of searching the components is unpredictable, avoid duplicate WHEN_IN_FOCUSED_WINDOW bindings!
It's because of this segment in 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;
}
}
So the order of searching is actually predictable, but obviously dependent on this particular implementation, so it's better not to rely on it at all. Keep it unpredictable.
(Javadoc and code is from jdk1.6.0_b105 on WinXP.)
We need to start debugging from Component.dispatchEventImpl. Just reading through the source comments of the method should give you the perfect idea of how events flow in Swing(you can also start one level up from EventQueue.pumpEventsForHeirarchy).
For clarity just let me give an extract from the code:
Set timestamp and modifiers of current event.; Pre-dispatchers. Do any necessary retargeting/reordering here before we notify AWTEventListeners.
Allow the Toolkit to pass this event to AWTEventListeners.
If no one has consumed a key event, allow the KeyboardFocusManager to process it.
Allow input methods to process the event
Pre-process any special events before delivery
Deliver event for normal processing
Special handling for 4061116 : Hook for browser to close modal dialogs.:)
Allow the peer to process the event. Except KeyEvents, they will be processed by peer after all KeyEventPostProcessors (see DefaultKeyboardFocusManager.dispatchKeyEvent())
Now you can match the above flow with your description to determine whether its right or not. But the point is you should really not depend on javadocs of private classes, the reason being that the developers usually dont care to update the comments of private classes when code changes, so the docs may become obsolete.
Related
I need to to make for school a simple "strategy game simulator". To do this I need to make an Event Dispatcher (event loop) that will send the event to the registered parties. For example, I have resources on the map. One event is "resource at location 1 depleted". And one "player" is interested on that event.
How would I create the dispatcher (and register one player for one particular event). Also, how does the dispatcher check for the event? Does it simply do something like if(resourceLocation1.getNoResource()==0) trigerEvent(); or is there some other, more elegant way.
I worked with event listeners (mostly in ActionScrip3) but never made a custom event and a custom event dispatcher. Any help is appreciated, including some links to some tutorials or sample codes.
If I am not clear what I am searching for please let me know and I will try to explain it better
Thanks.
Your EventDispatcher does not need to check every possible condition and notify all possible listeners. Just notify listeners registered for a certain type of event.
Register Player to be notified depending on the game event
eventDispatcher.register(player, Events.RESOURCE_DEPLETION_EVENT);
Then your Resource would supply an event when resources reached 0
class Resource {
public void deplete(int amount) {
this.amount -= amount;
if (this.amount <= 0)
eventDispatcher.notify(this, Events.RESOURCE_DEPLETION_EVENT);
}
}
Otherwise you are going to end up with a massive logic-containing event loop that eats up performance and will be difficult to debug.
Java has a built-in thread-safe Observer pattern you can use.
To write your own you would have Player implement a ResourceDepeletionListener interface and add it to an array of listeners in your Resource class. When the resources reach zero they call resourcesDepleted() on all ResourceDepeletionListener objects.
What about implementing an observer pattern?
For instance, you can have a ResourceObserver, which registers a particular Resource as an observable. From there, you can have Player objects register as observers to your ResourceObserver. A map object will hold all the resources. In your event loop, you will have something like:
...
Map.updateResources();
...
So for instance, when you call updateResources, all the map resources will check if they have been depleted. If a resource has been depeleted, it will notify it's ResourceObserver, which will in turn notify all registered players for that resource.
Let me first sketch the concrete situation I find myself in, although my question is actually more general. I'm writing a component containing several sliders and I have listeners listening for events from these sliders. When one of these sliders changes I want my component to send an event to its own listeners to notify them that its state has changed. I would however like to limit the number of events that are sent, i.e. if there are several events waiting when my component notifies its listeners, I would like to collapse all these events into a single event.
My question is whether there are standard techniques for this. If so, any example would be welcome, because I couldn't find any. (Maybe collapsing is not the correct terminology?)
I believe collapsing is the correct term. An example class from the Java Core libraries that implements such behavior is RepaintManager. I would check out it's source code to see how it collapses multiple repaint requests.
Before you do any such thing you should make sure that it is really necessary.
I guess you would need to access the EventQueue from your listener. When an event triggers the callback method, this method should first look in the queue to see if there are more recent events of the relevant type and, if so, process the most recent event only and then remove all events of that type from the queue.
Since the callbacks are always on the Swing (awt) event thread, you don't need to worry about concurrency.
I am looking for a way to do what the InvokeLater() function does only instead of putting the event on the bottom of the event queue it puts it on top. At least I think that will do what I want, maybe there's a better way. Below describes what I'm trying to replicate.
Years ago I use a c++ framework on the Mac that had feature that you could add a Chore object to a CriticalChore list while processing the current event. You would do this while executing code in what amounts to Swings EDT. After the current event was finished being processed and just before calling GetNextEvent() the Framework would check if the CriticalChore list was empty. If the list had items in it there Perform() (i.e. run()) function would be called. When finished with the list all the items were then deleted.
This feature came in really handy. Many times while handling an event early on you know you need to perform some additional code but only after a lot of other code is processed. But most importantly, is this code needs to be processed before any other events from the EDT queue are handled.
I don't see any method of doing that. I suppose that you could do some hacky stuff to make your own method of injecting higher priority actions.
I think the best answer, though, is to not do this at all. If you have a need to do so, the design probably needs to be reworked. The EventDispatchThread is supposed to be only for very short-running actions as it's never supposed to look to the end user as though the application has frozen. Because of this, the queue for the EDT should always be short enough that anything you put on it will happen "instantly" from the point of view of the user, so everything on it should have "instant" priority.
If anything needs to be done which is not a very short-lived action, there is a separate methodology for doing that. There is a Swing Worker class for that, and you are supposed to use this to set up tasks that run alongside the EDT and listen for its responses.
Here is a Swing Worker Tutorial. There are also some other good ones that Google pulls up with a "Java SwingWorker tutorial" query.
First, how's done
It's possible to install a global listener with its own queue and one each event polling the queue. Toolkit.addAWTEventListener(listener, eventMask)
There is a sun.awt.PeerEvent (for sun impl) that has an ultimate priority which offers the easiest impl since it's practically the same as EventQueue.invokeLater extending java.awt.event.InvocationEvent but again it's not standard.
Last:
Here how is done standard way, I have not tested the code, though (lazy & very late)
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);
}
};
Use the EventQueueX.install() and then pushFirst(e) when you want an event and you're set. Unfortunately the queue will get deinstalled on an exception and might be pushed away too.
Next, why is bad
To the question. putting an event in the front of the queue is a bad idea overall.
If you have to call any code later on just structure your own design and at the end of the function invoke the necessary code, use a Queue if you need be.
Adding an extra layer of super ultimate priority might look ok, but it's a hard to understand design concept for any regular AWT/Swing (UI mostly) developer. If you need to queue actions, use your own mini-framework w/o messing up with awt. While I am particularly good at hacking, even I, myself, would fine such an approach weird (to put it mildly).
In general terms of java, there are listeners & handlers for events.
I mean I use them unknowingly, just whichever is available in the API.
My question is, in what case do we use listeners and in what case do we use handlers for events?
What's the difference between them? Characteristics??
I've searched for reasons and I couldn't find a proper explanation for Java.
There's no formally defined difference between listeners and handlers. Some people would probably argue that they are interchangeable. To me however, they have slightly different meaning.
A listener is an object that subscribes for events from a source. Cf. the observer pattern. Usually you can have many listeners subscribing for each type of event, and they are added through addXyzListener methods.
Example: The MouseListener in the Java API.
A handler is an object that is responsible for handling certain events. A typical scenario would be to provide a handler for a specific event/task as an argument to a constructor, or set the handler through a setXyzHandler method. In other words, you usually have one handler for each type of event.
Example: The MemoryHandler in the Java API.
The most basic difference is the association
Listener is associated with Event Source (Ex: key board)
Handler is associated with an Event (Ex: keydown)
Generally speaking, there will only one central Handler Manager which manages all the events, while in case of Listener each Entity which wants to listen, will have to manage their own Collection of listeners
This is the way I see it:
A listener watches for an event to be fired. For example, a KeyListener waits for KeyEvents, a MessageListener waits for messages to arrive on a queue and so on.
The handler is responsible for dealing with the event. Normally, listeners and handlers go hand-in-hand. For example, the KeyListener tells the ExitHandler that "the letter Q was pressed" and the handler performs logic such as cleaning up resources and exiting the application gracefully. Similary a ButtonClickListener would tell the same ExitHandler that the "Exit button was clicked". So, in this case you have two different events, two different listeners but a single handler.
A listener is an object that is notified when an event occurs, and it has 2 major requirements-
1-it must have been registered with one or more sources to receive notifications about specific types of event
2-it must implements methods to receive and process these notifications.
Handler is responsible for dealing with events.
To my mind, the most important difference is fact that we use listeners per event's source, in contrary to handler, which is per event type.
A listener, listens for events which are data value objects which describe an event. When the event occurred and the order of events is often important. Pressing key '0' followed by '1' is different to '1' and '0'.
A handler, handles a complex object e.g. a new Socket connection. The handler might process the object for any length of time. The time of object creation and order is not so important. A connection from client0 or client1 can happen in any order.
I think the difference is subtle because a concrete Listener is an event-handler too or at least has a method that can be considered an event-handler.
That is, a concrete Listener handles or manages the reaction to the event after receiving an event object(from the event-source) with all the usefull informations about the event just occurred(on the event-source).
As this Listener has to implement an xxxListener interface that forces him to implement at least one method that is in turn executed by the event-source object when the event occurs, so the Listener itself can be considered an handler and more precisely, the method of the Listener interface implemented by the Listener object can be considered the real event-handler.
So i view the event-handler as just the code that is executed in reaction to an event.
This is different from a Listener object that is an element of a more abstract concept such as an Observer design pattern.
This is my personal view of the subject.
They're conceptually the same thing - an object that performs some action in response to a UI event. Generally, in Swing, these objects are called "handlers" at the look-and-feel level (for handling low-level widget events), and "listeners" at the more abstract UI level (where you'll be implementing your application logic).
EventHandler is introduced in the JavaFX for all the UI controls. Whereas the Listener is borrowed for Observables, such as properties.
The EventHandler is a way to distinguish observable events and the ui events.
I've been trying to make sense of all the info and I'm lost. I've looked at Delphi (Pascal), C, C++, java... nothing is clear.So, after a month, this is the problem as I see it. I may be totally off track, so please tell me... politely, please.
One event sender, one catcher as long as Sender registers the catcher. I have 4 dialog boxes that need to be updated each time a file (whose handling code is in another module than the 4 dialog boxes) changes. I considered updating each the old-fashioned way, but then I looked at Delphi events and message handling. Let's see:
File F (The Sender) is finished reading and should notify Dialogs 1..4 of the fact that there is now data for them to display and the user to play with. What is best?
Try to register Dialogs 1..4 as listeners and have the Sender trigger an OnUpdatedDataEvent somehow?
Try sending a message across the system, hoping that Dialogs 1..4 will catch it?
Notice that the event keeps things coupled while messaging do not...and are a pain to debug.
And I do wonder how the File block of code will be able to register 4 listeners (the dialog boxes)?
What I am looking at is the possibility of cascade calling, meaning caller calls one listener, whom calls the next... until it reaches the end of the chain. I even wonder if that is even possible.
An example:
Say File F is a list of languages. Now, DialogBox 1 does something to the list (adds a new language for instance); that combo box updates the F file; this in turn triggers a DataUpdatedEvent. the 4 Dialog boxes contain, say, TComboBoxes that display the language list when they pop up. I want the 4 boxes to notice the change and update their own combo box contents with the freshly updated File... without having to worry about how the combo boxes know they need to refresh their contents. If it works as envisioned the Sender parameter will carry across and the dialog box that triggered the dataUpdateEvent will be bypassed since it will already be updated. After all an if sender=self then continue to next event handler should be easy to implement.
All that because I want to exercise my brain... to prevent Alzheimer's, not very successfully I might add.
Suppose you just landed at the airport by plane at a new destination. you have someone waiting for you at the gate OR someone who will drive the taxi and take you to your hotel
The person waiting is the listener (waiting for an event like you are arriving)
The person taking you to the hotel is the event handler (the action after you've arrived)
In JS, the listener waits for an event (e.g click) the handler does something father the "click" happened
It is semantics.
Listener is interface.
Adaptor is class that implements specific interface and provides empty implementation for its methods. This helps if you do not have to implement all methods of interface.
Handler implements several interfaces or delegates calls to several interfaces.
I was wondering if the following is common for "regular" Java applications when receiving callback/events. Those callbacks may be triggered by user input but also by other means so it is not only related to UI events:
public void handleEvent( #NotNull final SomeEvent e ) {
final boolean process;
synchronized ( this ) {
process = !e.equals(filter);
filter = e;
}
if ( process ) {
...
}
}
Basically under some complicated scheme (very complex UI involving several views of a same model and where the user can modify the model from different screens [like in complex 3D programs]) I've got lots of events firing and I've noticed that I could filter out duplicate events using the above snippet. If an event has been processed and the next event to come is exactly identical to the last processed event (saved in the filter reference), then the event/callback is simply ignored.
It works fine. I was wondering if filtering out duplicate events was a common technique?
Not always, but usually this can be a sign that some elements of the event cascade chain aren't properly detecting that they don't need to send an event. The classic illustration is a bean setter that generates a PropertyChangeEvent even when the value hasn't changed.
While what you've done will filter these events out, it doesn't address what may be a fundamental underlying issue.
The problem is that these "errors" can combine to form infinite loops. Extending the bean example above, say you have a UI that resets its editable value based on that bean field... and resetting the UI value will also call the bean setter because proper dupe checking wasn't done there either. The first time the value is edited and endless loop will occur.
These examples are obvious when they happen but as notification hierarchies get more complicated it becomes harder to track these things down and they potentially occur at more intermittent times.
A good rule of thumb is to make every event generating component as conservative as possible. In the event (heh) you are receiving notifications from components that you can't control, and will be forwarding your own events also then a filter like the one you've setup may be the only option to prevent the spread of a potentially larger problem than just performance.
The only thing I can think of is acting on a ListSelectionEvent based on whether the selection is still changing (i.e. the user is still clicking and dragging the mouse) or whether the event represents the "final" selection event; e.g.
public class MyListSelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent evt) {
// Finished selecting
if (!evt.getValueIsAdjusting()) {
JOptionPane.showMessageDialog("Selection Complete!");
}
}
}
Looks like you might have a listener registered twice to the same source. That could cause it. Or possibly you've registered a single listener across multiple instances. If you're seeing strangeness, look for infinite event loops which, unfortunately, because of the way Swing program organize themselves, can happen all too easily. You'll want to break those listeners apart.
I've never done this sort of thing or encountered it. As some people point out certain controls will fire events when selections are being adjusted, but there are methods to filter those things out.
The synchronized( this ) block is suspect too since you'll always be called back on the Swing thread. If that's not true in your program then you are violating Swing's threading rule, and that could explain the problem. Bottom line is you don't need the synchronized block because Swing is single threaded.
(I'm assuming this is Swing as some other posters have, but from your code alone it's ambiguous).