I'd like to ask you couple of question about Gui.
I saw the following example:
public class ShellWithButton {
public static void main(String[] args) {
Display display = Display.getDefault();
Shell shell = newShell (display);
Button ok = newButton (shell, SWT.PUSH);
ok.setText ("Push Me!");
ok.addSelectionListener(new ButtonHandler());
ok.setLocation(0,0);
ok.setSize(100,30);
shell.pack ();
shell.open ();
while(!shell.isDisposed ()) {
if(!display.readAndDispatch())
display.sleep ();
}
display.dispose ();
}
}
public class ButtonHandler
implements SelectionListener {
public void widgetSelected(SelectionEvent e) {
if(e.getSource() instanceofButton) {
Button b = (Button) e.getSource();
开发者_运维百科 b.setText("Thanks!");
}
}
public voidwidgetDefaultSelected(SelectionEvent e){
// TODO Auto-generated method stub
}
}
(i)- Someone pushes the button- How does the program know to activate widgetSelected? I can see that the button added the ButtonHandler listener to itself, but why that the pushing the button and not just clicking the box will send the event to ButtonHandler? I can't see where only the pushing was sent to this listener.
(ii)-why do I send an instance of the ButtonHandler to the listeners? what does that mean?
(iii)- what's happeing when I push the button? what is this event? event is an instance of the button itself?
(iv)- Button b = (Button) e.getSource();
why do I need this casting of the source? the event, as was written, can come only from ok, which is instance of button.
(v)- why that the original button will change its title? we change B.
Thank you very much!
When someone pushes the button, the button calls
widgetSelected()
because that's how the library was designed; it needs to call some method so you can do something and they settled on that method. The reason it calls YOURwidgetSelected()
is because you gave it your class for it to call. The button knows your class has awidgetSelected()
method because you implementedSelectionListener
, and that requires you to implement thewidgetSelected()
method. That is the very reason for interfaces, and I suggest you read up on them. Only clicking the button will get the button to call your method because the button only knows when it is clicked. When there is a click on the screen, only the widgets that need to know about it are told.As I mentioned above, you send your handler to the button so it knows what to do when it's pushed.
When the button is pushed, it has to tell your handler what happened, and so all the relevant information is given to you as a
SelectionEvent
. The event itself isn't the button, but the event tells you which button is pushed, in case you want the same handler to handle more than one button.You need the cast because your
widgetSelected()
method can be called when something happens to all sorts of GUI objects, not just buttons. Therefore, the source is given as some superclass common to all the widgets that can call your method, and you need to cast it back to a button when you're sure it's your button. Yes, in this program it can only be called by the button, but that's not always the case.The button's text changes because B and the button you created and displayed are the same object. Objects (and arrays) in Java are "pointers," they tell you where the object is. When you assign one object to another variable, you're not copying the object, you're just using another variable to point to the same object.
(i) GUI usually uses the observer pattern, in which one or more objects subscribe to an event, and whenever this event happens it is send to all the subscribed objects, just like in your button case.
(ii) You send the instance to the listeners in order to associate them, so they may receive the event when appropriate.
(iii) What happens is that the event is causing the observers to receive a notification that your button was pushed, which eventually leads to some code being executed. The event itself is not an instance of the button, but rather a separate instance to handle the events.
(iv) You need to cast it, because the method signature is just generic, since it is used for several types of events.
(v) It changed its title, because using the observer pattern, the observer in this case your button was notified when the event which was pressing the button happened.
(i) The idea behind "Listeners" is that you want to provide a list of components, object, software modules, etc. that will be notified of the event. The reason the button click doesn't just trigger something is because something's got to be listening for that event in order to react to it. Any object implementing the appropriate Listener interface (depending on the type of event) can be added, and therefore process the event.
(ii) It's a callback. You have to tell the Listener, "Here's an instance of an object that can handle your events. Please add it to the list of objects to be notified." It's kind of like subscribing to an RSS feed, in a sense - everyone on the list gets the update when it happens.
(iii) The event is a separate object. The windowing system (which, at some deep level, connects to the windowing library of the underlying OS) creates the event object, and then goes down the list of registered Listeners, notifying each of them. There are some exceptions to this (for example, it's possible for a Listener to absorb an event, preventing anyone else on the list from hearing it, but that's a separate question of its own)
(iv) Because getSource() returns an instance of a component. If you want to be able to access the Button-specific methods (which is done in the following line, with setText
, you have to be dealing with an instance of Button for that method call to know what to do (i.e. which class on which to operate).
(v) The button isn't changing it's title - the ButtonHandler is doing it. So, when the widget gets selected, the "widgetSelected" method gets called inside the ButtonHandler. It then checks the source of the event (which provides a reference to the original button) and then updates the button's text to reflect that it's been clicked.
精彩评论