Java Programming Notes # 2558
- Preface
- General
background information - Preview
- Discussion and
sample code - GwtApp019 – Creation of an HTML element or DOM node using the
GWT. - GwtApp020 – Determining the state of the Alt key when a click
event is fired. - GwtApp021 – Determining which mouse button was pressed when a
mouse event is fired. - GwtApp022 – Dynamically controlling the style of GUI
components at runtime. - DoubleClick01 – Illustrates the simplicity of single versus
double-click event handling in standard Java. - GwtApp023 – Handling double-click events in the GWT.
- Run the programs
- Summary
- What’s next?
- Complete program
listings - Copyright
- Download
- Resources
- About the author
Preface
General
Historically, the development of Ajax web applications has been a complex
process. This is due mainly to the requirement to learn and use a variety of
technologies, such as HTML, JavaScript, XML, ASP.NET, Java servlets, various
scripting languages, etc.
Recently several products have emerged that make it possible to develop Ajax
web applications using the Java development environment. Some use exclusively
Java, while others use mainly Java. I have discussed several of these new
programming environments in previous lessons in this series (see
Resources).
The Google Web Toolkit (GWT)
One development environment that allows you to use mainly Java for the
development of web applications is the Google Web Toolkit (GWT) (see
Resources and
Download), which is the primary topic
of this tutorial lesson.
Most of the client-side code for a GWT Ajax application can be written in
Java. There is no requirement to write JavaScript code. As you will
see in this lesson, however, it is sometimes necessary to think about the
JavaScript code.
Fifth in a series
This is the fifth lesson in a series designed to help you learn
how to use the GWT to create rich Ajax web applications. You will find links to
the previous lessons in the series in the
Resources section.
Purpose of the tutorial
The main purpose of the tutorial is to teach you how to write
the Java code necessary to make effective use of the DOM class in the GWT.
Viewing tip
I recommend that you open another copy of this document in a separate
browser window and use the following links to easily find and view the figures
and listings while you are reading about them. You may also find it useful
to open a third browser window at the Resources section near the end of the
document. That will make it easy for you to open those resources when they
are mentioned in the text.
Figures
- Figure 1. Creating a DOM node using the GWT.
- Figure 2. The application GUI at startup.
- Figure 3. GUI after clicking the button.
- Figure 4. GUI after clicking the button with Alt
key depressed. - Figure 5. Button clicked with middle mouse
button. - Figure 6. Application GUI for GwtApp022 at
startup. - Figure 7. Application GUI after clicking the
button once. - Figure 8. Application GUI after clicking the
button twice. - Figure 9. GUI for DoubleClick01 after
single-click on button. - Figure 10. GUI after double-click on button.
- Figure 11. A basic problem in the GWT.
- Figure 12. Application GUI at startup for
GwtApp023. - Figure 13. Application GUI after clicking both
buttons. - Figure 14. The state of focus of the top
button.
Listings
- Listing 1. HTML host page for GwtApp019.
- Listing 2. Java code for GwtApp019.
- Listing 3. Beginning of the class definition
for GwtApp020. - Listing 4. Register an EventPreview listener
object. - Listing 5. Add the GUI button and the label to
the RootPanel. - Listing 6. An EventPreview listener class.
- Listing 7. An inner ClickListener class.
- Listing 8. The onModuleLoad method for
GwtApp021. - Listing 9. The EventPreview class.
- Listing 10. The MouseListener class.
- Listing 11. Begin class definition for
GwtApp022. - Listing 12. Register a click listener on the
button. - Listing 13. Cycle the colors.
- Listing 14. Beginning of the code for
DoubleClick01. - Listing 15. Beginning of the constructor.
- Listing 16. An anonymous mouse listener.
- Listing 17. Familiar code.
- Listing 18. Register an EventPreview filter.
- Listing 19. Beginning of the EventPreview
filter code. - Listing 20. Display on command-line screen.
- Listing 21. Process double-click events.
- Listing 22. Not a double-click event.
- Listing 23. HTML host page for GwtApp019.
- Listing 24. Java code for GwtApp019.
- Listing 25. HTML host page for GwtApp020.
- Listing 26. Java code for GwtApp020.
- Listing 27. HTML host page for GwtApp021.
- Listing 28. Java code for GwtApp021.
- Listing 29. HTML host page for GwtApp022.
- Listing 30. Java code for GwtApp022.
- Listing 31. Java code for DoubleClick01.
- Listing 32. HTML host page for GwtApp023.
- Listing 33. Java code for GwtApp023.
Supplementary material
I recommend that you also study the other lessons in my extensive collection
of online Java tutorials. You will find a consolidated index at
www.DickBaldwin.com.
General background information
What is the DOM class and why should you care?
According to the javadocs on the GWT, the DOM class "… provides a
set of static methods that allow you to manipulate the browser’s Document Object
Model (DOM). It contains methods for manipulating both elements and events."
Not a fun place to be
In truth, this is a class that you would probably just as soon not have to
use, particularly if your strong suite is Java and not JavaScript. Any
time you have to use the DOM class, you probably have to think
about HTML, JavaScript, or both. However, you will probably encounter
things that you need to do in your web applications that you can only do by
using methods of the DOM class.
A requirement for drag-and-drop
For example, in the previous lesson entitled "Focus events, click events, and
Drag-and Drop in AJAX using the GWT and Java" (see Resources), it was
necessary to invoke the setCapture method of the DOM class to make
certain that the mouse would not lose the button as the button slid underneath
another component while the button was being dragged. I don’t know of any
way to accomplish that in the GWT without using a method of the DOM
class.
Would prefer not to have to think about JavaScript
or HTML
Usually when we are using Java and the GWT to develop a web application, we
would usually prefer not to have to think about JavaScript or HTML.
However, it is not possible in some cases to totally ignore JavaScript and HTML.
Sometimes we have to think about them and do something that involves one or the
other or both. In reality, when a situation like that occurs, we usually
need to do something that involves the Document Object Model (DOM) tree
(see Resources) that represents the web page.
What is the DOM tree?
Instruction on the DOM tree is well beyond the scope of this tutorial, but
you can read all about it on the W3C website (see
Resources). The DOM class in the GWT defines about ninety
different static methods that you can use to manipulate the DOM tree in your web
application.
Will discuss a subset of the available methods
Given that the DOM class contains such a large number of different methods, it
won’t be possible for me to teach you about all the capabilities that derive
from those methods in this lesson. However, I will teach you about
five different capabilities that the methods support in different ways.
Hopefully, that will give you enough of a background on the topic that you can
progress from there on your own.
Preview
Five GWT applications and one standard Java
application
I will present and explain five sample GWT applications and one standard Java
application in this lesson. The names of the applications are shown in the
following list. This list also shows the primary topic that each application is
designed to illustrate.
- GwtApp019 – Creation of an HTML element or DOM node using the
GWT. - GwtApp020 – Using the EventPreview capability to determine
the state of the Alt key when a click event is fired - GwtApp021 – Determining which mouse button was pressed to cause a
mouse event to be fired. - GwtApp022 – Dynamically controlling the style of GUI components
at runtime. - DoubleClick01 – Illustrates the simplicity of single versus
double-click event handling in standard Java. - GwtApp023 – Handling double-click events in the GWT.
Discussion
and sample code
Complete program listings
I will discuss
the code for the following applications in fragments. A complete listing of
each application is provided in Listing 23 through Listing 33 near the end of
the lesson.
The HTML host pages
With one exception, the HTML host pages used for the applications in this
lesson are essentially the same as those used for the applications in my earlier
tutorials. I will explain the one that is different, but I won’t discuss the
others in this lesson. However, a complete listing of each HTML host page is
also provided in Listing 23 through Listing 33 along with the Java source code
for the application.
GwtApp019 – Creation of an HTML element or
DOM node using the GWT
The purpose of this application is to demonstrate the use of a method of the
DOM class to create of a new DOM node. The application GUI is shown
in Figure 1.
Figure 1. Creating a DOM node using the GWT.
|
As you will see shortly, the boldface line of text in Figure 1 was created from a static
h3 element in the HTML host page.
A
dynamically created paragraph
However, the paragraph below that header was not included in the HTML host page.
Rather, it was generated dynamically at runtime by the code in the GWT.
HTML host page for GwtApp019
The HTML host page for this application is shown in Listing 1. An HTML
comment shows the location at which the new element is created at runtime. Note that an ID attribute is assigned to the
body element in the host HTML
page to make it accessible to the Java code. This is the only thing that makes
this HTML host page different from most of the host pages that you have seen in
earlier lessons.
Listing 1. HTML host page for GwtApp019.
<!-------------------------------------------------------- File GwtApp019.html GWT host page. ---------------------------------------------------------> <html> <head> <title>Wrapper HTML for GwtApp019</title> <meta name='gwt:module' content='GwtApp.GwtApp019'> </head> <!--Assign an ID to the body element to make it accessible by the Java code--> <body id="rootNode"> <script language="javascript" src="gwt.js"></script> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe> <h3>GwtApp019</h3> <!--A paragraph element will be placed here in the output HTML by the Java code--> </body> </html> |
It may be possible to accomplish what this application accomplishes without a
requirement to establish such an ID attribute, but it wasn’t obvious to me how
to do so.
Java code for GwtApp019
The Java source code for this application is shown in its entirety in Listing
2.
Listing 2. Java code for GwtApp019.
package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; public class GwtApp019 implements EntryPoint{ //This is the entry point method. public void onModuleLoad(){ //Get a handle on the root node of the DOM tree. Element rootNode = DOM.getElementById("rootNode"); //Text to be displayed in the paragraph element that // will be generated using Java code. String para = "This paragraph element was generated " + "by the Java code."; //Create and populate the new paragraph element. Element pElement = DOM.createElement("<p>"); DOM.setInnerText(pElement,para); //Append the new paragraph element to the DOM tree. DOM.appendChild(rootNode,pElement); }//end onModuleLoad method //====================================================// }//end class GwtApp019 |
Get a handle on the root node
The source code begins by using a static method of the DOM class named
getElementById to get and save a handle on the root node of the
DOM tree (the body element).
Create and populate a new paragraph element
Then it uses the following two static methods of the DOM class to
create and populate a new paragraph element.
- createElement
- setInnerText
|
Append the new element to the DOM tree
Finally, it uses a static
method of the DOM class named appendChild to append the new node (the new paragraph element) to
the DOM tree.
When the application is executed, the new paragraph element is created and displayed
as shown in Figure 1.
Testing
This application was tested using J2SE 5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27
running as a localhost server under WinXP.
GwtApp020 – Determining the state of the Alt
key when a click event is fired
The event preview capability
This application will introduce you to a very important capability made
available to the GWT by the DOM class. This is the capability to preview events before
they are handled by registered event handlers and possibly to intervene in some
way before they are handled. This capability will be used extensively in
the subsequent applications in this lesson.
What key or keys were pressed?
Sometimes you need to know whether the user was holding down the Alt key, the
Shift key, or the Ctrl key when an event is fired. This application will
teach you how to use the event preview capability to determine the state of the
Alt key when a click event is fired. You should be able to extend that
knowledge to cover the Shift key and the Ctrl key on your own.
The application GUI at startup
Figure 2 shows the application GUI at startup, before the user clicks the
button with the mouse.
Figure 2. The application GUI at startup.
As you can see, the label at the bottom displays the default text "Startup."
GUI after clicking the button
Figure 3 shows the GUI after the user has clicked the button with the mouse.
Figure 3. GUI after clicking the button.
At this point, the label at the bottom indicates that the Alt key was not
depressed when the click event was fired.
GUI after clicking the button with Alt key depressed
Figure 4 shows the GUI after the user has clicked the button with the mouse
while holding down the Alt key.
Figure 4. GUI after clicking the button with Alt key
depressed.
In this case, the label at the bottom indicates that the Alt key was
depressed when the click event was fired. This demonstrates that it is
possible to determine if the Alt key is being held down when a click event is
fired. Although it won’t be demonstrated in this lesson, as mentioned
earlier, similar code can
be used to determine if the Shift key or the Ctrl key is depressed when a click
event is fired.
Description of the application
As mentioned earlier, the purpose of this application is to introduce the
event preview capability of the DOM class. An object of a class
that implements the EventPreview interface is registered using a static
method of the DOM class to preview all events. When an event is
fired in this application, a reference to the event is saved in an instance variable named
theEvent. This reference is used later by the onClick method of
a ClickListener object registered on a GUI button to determine the state
of the Alt key when the click event was fired.
The application was tested using J2SE 5.0, GWT version 1.2.22, and
jakarta-tomcat-5.0.27 running as a localhost server under WinXP.
Beginning of the class definition
The class definition for GwtApp020 begins in Listing 3.
Listing 3. Beginning of the class definition for
GwtApp020.
package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp020 implements EntryPoint{ //The contents of this label are modified by the onClick // method when the user clicks a GUI button. Label label = new Label("Startup"); //The following variable is used to store a reference to // each event that is fired. When the GUI button fires // a click event, this reference is used to determine // the state of the Alt key when the user clicked the // GUI button with the mouse. Event theEvent; public void onModuleLoad(){ //Instantiate a new Button object and register a click // listener on it. Button button = new Button("Click Me"); button.addClickListener(new ClickLstnr()); |
The code in Listing 3 is straightforward and shouldn’t require an explanation
beyond that provided by the comments.
Register an EventPreview listener object
Listing 4 uses a static method of the DOM class to register an EventPreview listener object.
Listing 4. Register an EventPreview listener object.
DOM.addEventPreview(new EventPrevue()); |
Register it on what?
Normally when we register a listener object, we register it on a specific
component. As you can see from Listing 4, however, this listener object
isn’t being registered on any specific component. I suppose we might say
that it is being registered on the entire application. In any event, the
EventPreview listener will have an opportunity to preview all events
fired anywhere in the application before they are delivered to listener objects
that are registered on specific components.
Add the GUI button and the label to the RootPanel
Listing 5 completes the onModuleLoad method by adding the button and
the label to the RootPanel as shown in Figure 2.
Listing 5. Add the GUI button and the label to the RootPanel.
RootPanel.get().add(button); RootPanel.get().add(label); }//end onModuleLoad method |
An EventPreview listener class
Listing 6 defines an inner (member) listener class that implements the
EventPreview interface.
Listing 6. An EventPreview listener class.
class EventPrevue implements EventPreview{ public boolean onEventPreview(Event event){ theEvent = event; return true;//Don't cancel the event. }//end onEventPreview }//end class EventPrevue |
Recall that an object of this class is registered on the application using
a static method of the DOM class to preview all events in Listing 5.
Save a reference to the Event object
When any event is fired within the application, a reference to the event is
saved in the instance variable named theEvent by the code in Listing 6.
This reference is used later by the onClick method of a ClickListener
object to determine and display the state of the Alt key when the event was
fired.
Don’t cancel the event
The onEventPreview method in Listing 6 returns true to prevent
the event from being cancelled. If the method were to return false,
the event would be cancelled and would not be delivered to the ClickListener
object that is registered on the GUI button.
An inner ClickListener class
Listing 7 defines an inner class that implements the ClickListener
interface.
Listing 7. An inner ClickListener class.
class ClickLstnr implements ClickListener{ public void onClick(Widget sender){ if(DOM.eventGetAltKey(theEvent)){ label.setText("Alt key is down."); }else{ label.setText("Alt key is up."); }//end else }//end onClick }//end class ClickLstnr }//end class GwtApp020 |
An object of this class is registered on the GUI button in Listing 3.
When the user clicks the GUI button with the mouse, the code in this event
handler uses a static method of the DOM class named eventGetAltKey along
with the reference to the event that was saved during the event preview process
to determine and display the state of the Alt key when the event was fired.
The text in the label is set to reflect the state of the Alt key as shown in
Figure 3 and Figure 4
Testing the Shift and Ctrl keys
In addition to the method named eventGetAltKey, the DOM class
also defines the following static methods that can be used to determine the
state of the Ctrl key and the Shift key when any event is fired:
- eventGetCtrlKey
- eventGetShiftKey
End of the class
Listing 7 also signals the end of the GwtApp020 class and the end of
the discussion of the application having the same name.
GwtApp021 – Determining which mouse button
was pressed when a mouse event is fired
While describing the drag-and-drop sample application in the lesson titled
"Focus events, click events, and Drag-and Drop in AJAX using the GWT and Java"
(see Resources) I identified a potential
problem. I told you that the GUI button could be dragged across the screen
by pressing any of the three mouse buttons on the GUI button to execute the drag
operation.
That is not normally how we would want a web application to behave.
Normally, we would want to reserve the drag operation for a specific mouse
button and use the other two mouse buttons for other purposes. This, of
course, requires you to be able to write your code in such a way that it knows
which mouse button was pressed. That is the main topic of this
application.
The application GUI
Figure 5 shows the result of clicking the large GUI button with the middle
mouse button.
Figure 5. Button clicked with middle mouse button.
Label identifies the mouse button
As you can see, the label at the bottom reports on which mouse button was
pressed to cause the event to be fired. Clicking the GUI button with the
left or right mouse buttons cause a similar report to appear in the label,
except that the corresponding mouse button is identified in the label.
Description of the application
The purpose of this application is to demonstrate the ability to determine
which mouse button was pressed when a mouse event is fired.
An object of a class that implements the EventPreview interface is
registered on the application using a static method of the DOM class to
preview all events. When any event is fired, a reference to the event is
saved in an instance variable named theEvent. This reference is
used later by the onMouseDown method of a MouseListener object
registered on the GUI button shown in Figure 5. The purpose of the
MouseListener object is to determine and to display which mouse button was
pressed, causing the mouse event to be fired.
Recall that as standard Button object in the GWT is not capable of
firing mouse events. Therefore, the GUI button used in this application is a custom button (like the one in the earlier lesson
titled "Focus events, click events, and Drag-and Drop in AJAX using the GWT and
Java – see Resources) that knows how to fire mouse
events.
The application was tested using J2SE 5.0, GWT version 1.2.22, and
jakarta-tomcat-5.0.27 running as a localhost server under WinXP.
The onModuleLoad method
The beginning of the class and the complete onModuleLoad method are
shown in Listing 8.
Listing 8. The onModuleLoad method for GwtApp021.
package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp021 implements EntryPoint{ //The contents of this label are modified by the // onMouseDown method when the user clicks a GUI // inputButton causing the inputButton to fire a mouse // event. Label outputLabel = new Label("Startup"); //The following variable is used to store a reference // to each event that is fired. When the GUI // inputButton fires a mouse event, this reference is // used to determine which mouse button was pressed. Event theEvent; public void onModuleLoad(){ //Instantiate a new custom button object and register // a mouse listener on it. This custom button knows // how to fire mouse events. Button button = new Button("Mouse Me"); button.setSize("100px","50px"); FocusPanel inputButton = new FocusPanel(button); inputButton.setSize("100px","50px"); //Cause the focus to skip the FocusPanel and go // straight to the button that is wrapped in the // FocusPanel. inputButton.setTabIndex(-1); //Register a mouse listener on the GUI inputButton. inputButton.addMouseListener(new MouseLstnr()); //Use a static method of the DOM class to register an // EventPreview listener object. DOM.addEventPreview(new EventPrevue()); //Add the GUI inputButton and the outputLabel to the // RootPanel. RootPanel.get().add(inputButton); RootPanel.get().add(outputLabel); }//end onModuleLoad method |
There is nothing new in Listing 8, and the code is heavily
commented. Therefore, I won’t discuss the code in Listing 8 further.
The EventPreview class
An inner listener class that implements the EventPreview interface is
shown in Listing 9.
Listing 9. The EventPreview class.
class EventPrevue implements EventPreview{ public boolean onEventPreview(Event event){ theEvent = event; return true;//Don't cancel the event. }//end onEventPreview }//end class EventPrevue |
An object of this class was registered on the application in Listing 8, using
a static method of the DOM class. This listener object previews all events
that are fired within the application. When an event is fired, a reference
to the event is saved in the instance variable named theEvent. This
reference is used later by the onMouseDown method to determine and
display which mouse button was pressed to cause the event to be fired. The
onEventPreview method returns true in Listing 9 to prevent the event from
being cancelled.
The MouseListener class
Listing 10 defines an inner listener class that implements the
MouseListener interface.
Listing 10. The MouseListener class.
class MouseLstnr extends MouseListenerAdapter{ public void onMouseDown(Widget sender,int x,int y){ int theMouseButton = DOM.eventGetButton(theEvent); if(theMouseButton == Event.BUTTON_LEFT){ outputLabel.setText("Left Mouse Button"); }else if(theMouseButton == Event.BUTTON_MIDDLE){ outputLabel.setText("Middle Mouse Button"); }else if(theMouseButton == Event.BUTTON_RIGHT){ outputLabel.setText("Right Mouse Button"); }else{ outputLabel.setText("Don't Know"); }//end else }//end onMouseDown }//end class MouseLstnr }//end class GwtApp021 |
Register the listener on the GUI button
An object of this class is registered on the GUI button in Listing 8. When the user clicks the GUI
button shown in Figure 5 with the mouse, the code in
this event handler uses a static method of the DOM class along with a reference
to the Event object and constants defined in the Event class to determine and display an identification of the mouse
button that was pressed to cause the event to be fired.
Otherwise, the code in Listing 10 is straightforward and shouldn’t require
additional explanation.
End of the class
Listing 21 also signals the end of the class named GwtApp021, and the
end of the discussion of the application having the same name.
GwtApp022 – Dynamically controlling the style
of GUI components at runtime
As you learned in an earlier lesson, you can control the style of GWT GUI
components through the use of a style sheet. That style sheet can either
be embedded in the HTML host page, referenced by the HTML host page, or both.
In his application, you will learn that you can also control the style of GUI
components dynamically at runtime through the use of Java code. This makes
it possible for the style of the components to change as a result of the firing
of different events as the execution of the application progresses.
Application GUI at startup
Figure 6 shows the application GUI at startup.
Figure 6. Application GUI for GwtApp022 at startup.
As you can see, the text on the face of the button is colored red.
Application GUI after clicking the button once
Figure 7 shows the GUI after clicking the button once following startup.
Figure 7. Application GUI after clicking the button
once.
Clicking the button once following startup causes the text on the face of the
button to change from red to green as show in Figure 7. Thus, the style of
the button has been modified as a result of the click event fired by the button.
Application GUI after clicking the button twice
Figure 8 shows the GUI after clicking the button twice following startup.
Figure 8. Application GUI after clicking the button
twice.
Clicking the button twice following startup causes the text to change from
red to green, and then from green to blue. Once again, this occurs as a
result of the click events fired by the button.
Application GUI after clicking the button three
times
Although I didn’t show it here, clicking the button three times following
startup causes the GUI to return to the state shown in Figure 6 with red text on
the face of the button. The third click event causes the text color to
change from blue back to red.
Cycle colors among red, green, and blue
In other words, each click event fired by the button causes the text on the
face of the button to change dynamically at runtime. The changes in color
trace out a repetitive pattern of red, green, blue, and back to red in that
order.
|
Description of the application
The purpose of this application is to use static methods of the DOM
class to dynamically control the style of GUI components at runtime.
As shown in Figure 6, the application:
- Instantiates a Button object.
- Uses a static method of the DOM class to set its style to red.
- Adds it to the root panel.
Then the application registers a click
listener on the button that causes the text on the button to cycle through the
colors of red, green, and blue each time the button is clicked.
The application was tested using J2SE
5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27 running as a localhost server
under WinXP.
Begin class definition for GwtApp022
Listing 11 shows the beginning of the class definition for GwtApp022.
Listing 11. Begin class definition for GwtApp022.
package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp022 implements EntryPoint{ public void onModuleLoad(){ //Instantiate a Button object, set its style to red, // and add it to the root panel. Button button = new Button("Button"); DOM.setStyleAttribute( button.getElement(),"color","#ff0000"); RootPanel.get().add(button); |
|
As you can see, after instantiating the Button object, the code in
Listing 11 invokes the setStyleAttribute to set its "color" attribute to
red (an attribute value of "#ff0000").
Method parameters
The three parameters to the setStyleAttribute method shown in Listing
11 are pretty interesting. The javadocs describe them in order as:
- The element whose style attribute is to be set.
- The name of the style attribute to be set.
- The style attribute’s new value.
When you compare the last two parameters in Listing 11 with the descriptions
of the parameters in the above list, the last two are pretty obvious. The
first one isn’t so obvious, however.
|
The getElement method
As you can see, Listing 11 invokes the getElement method on a
reference to the button. According to the javadocs, the getElement
method "Gets a handle to the object’s underlying DOM element." In
other words, this method makes it possible to manipulate the actual element in
the DOM tree that is represented by the Java object of type Button.
Add the button to the root panel
After the button is instantiated and has had its style set in Listing 11, it is
added to the root panel for display as shown in Figure 6.
Register a click listener on the button
Listing 12 shows the beginning of an anonymous inner class that registers a
click listener on the button in order to cycle the color of the text through
red, green, and blue each time the button is clicked.
Listing 12. Register a click listener on the button.
button.addClickListener( new ClickListener(){ public void onClick(Widget sender){ //Get a reference to the element that // represents the button, and then get the // current value of the color style for that // element. Element element = sender.getElement(); String attr = DOM.getStyleAttribute(element,"color"); |
Listing 12 gets a handle on the sender of the event as a DOM element,
(which must be the button in this case). Then it invokes the
getStyleAttribute method, passing the element and the name of the style
attribute of interest for the purpose of getting and saving the value of the
attribute.
Cycle the colors
Listing 13 shows the remaining code for the anonymous inner class, from which
a click listener object is instantiated and registered on the button.
Listing 13. Cycle the colors.
if(attr.equals("#ff0000")){ DOM.setStyleAttribute( element,"color","#00ff00"); }else if(attr.equals("#00ff00")){ DOM.setStyleAttribute( element,"color","#0000ff"); }else{ DOM.setStyleAttribute( element,"color","#ff0000"); }//end else }//end onClick }//end constructor );//end addClickListener }//end onModuleLoad method }//end class GwtApp022 |
Listing 13 executes the logic that cycles the color style through red, green, and blue each time the button is clicked.
This code is straightforward and shouldn’t require further explanation.
End of the class
Listing 13 also signals the end of the onModuleLoad method, the end of
the class named GwtApp022, and the end of the discussion of the
application having the same name.
DoubleClick01 – Illustrates the
simplicity of single versus double-click event handling in standard Java
Now I’m going to show you something a little different. The next
(and last) topic of interest in this lesson has to do with being able to
differentiate between single-click and double-click events. I’m going to
show you a standard Java application that illustrates the simplicity with which
such differentiation can be accomplished in standard Java. Following that,
I will show you how to accomplish part of the same thing with the GWT, which as you
will see isn’t quite so simple.
GUI for DoubleClick01 after single-click on button
Figure 9 shows the application GUI after the user has performed a
single-click on the button.
Figure 9. GUI for DoubleClick01 after single-click on
button.
The label on the right in Figure 9 indicates that the event was a
single-click event.
GUI after double-click on button
Similarly, Figure 10 shows the GUI after the user has performed a
double-click on the button.
Figure 10. GUI after double-click on button.
As you can see, the program can differentiate between the two, and can take a
different action depending on whether the event was a single-click event or a
double-click event.
Beginning of the code for DoubleClick01
The code for the desktop application named DoubleClick01 begins in
Listing 14.
Listing 14. Beginning of the code for DoubleClick01.
import java.awt.*; import javax.swing.*; import java.awt.event.*; class DoubleClick01 extends JFrame{ public static void main(String[] args){ new DoubleClick01(); }//end main |
The class named DoubleClick01 extends the JFrame class.
Hence, an object of the class is the program GUI.
The main method in Listing 14 instantiates an object of the
DoubleClick01 class, thus creating the GUI and causing it to be displayed.
Beginning of the constructor
Listing 15 declares and initializes a couple of instance variables to create
the button and the label shown in Figure 9. Then Listing 15 shows the
beginning of the constructor for the class.
Listing 15. Beginning of the constructor.
Button button = new Button("Click me"); Label label = new Label("Single-click"); DoubleClick01(){ setLayout(new FlowLayout()); add(button); add(label); setSize(250,100); setTitle("Copyright 2006,R.G.Baldwin"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); |
The constructor code in Listing 15 is straightforward, and should be
self-explanatory on the basis of the names of the methods that are invoked to
construct the GUI.
An anonymous mouse listener
Listing 16 defines, instantiates, and registers a MouseListener object
on the button.
Listing 16. An anonymous mouse listener.
button.addMouseListener( new MouseAdapter(){ public void mouseClicked(MouseEvent event){ switch(event.getClickCount()){ case 1:label.setText("Single-click");break; case 2:label.setText("Double-click");break; default: label.setText("Don't know"); }//end switch }//end mouseClicked }//end constructor );//end addMouseListener }//end constructor }//end class DoubleClick01 |
Listing 16 uses a standard Java switch statement go determine whether
the event was a single-click event or a double-click event and to display the
results in the label as shown in Figure 9 and Figure 10.
The incoming parameter
|
The critical thing about Listing 16 and the thing that makes this task so
easy in standard Java (which is totally missing in the GWT) is the
incoming parameter of type MouseEvent to the mouseClicked method.
|
This incoming parameter to the standard Java mouseClicked method is a reference to an object that encapsulates a lot
of information about the event. For example, the object encapsulates
information that makes it almost trivial to determine if the event was a
single-click or a double-click event. All that is necessary to get that
information is to invoke the getClickCount method on the incoming
parameter.
A choice between two different actions
Listing 16 invokes the getClickCount method on the incoming parameter,
and uses the information returned by that method to make a choice between two
different actions. Those two actions were purposely made very simple in
this example program, but could be as simple or as complex as may be necessary
to solve the problem at hand. The important point is that it is easy to
write the code necessary to make the choice.
|
I can’t make such a choice in the GWT
Quite frankly, I haven’t figured out how to make such a choice in the GWT.
It can probably be done, but I haven’t figured out how to do it, and so far, my
research on the web hasn’t led me to anything indicating that anyone else has
figured out how to do it either (except for some Rube Goldberg-like
approaches involving the use of a timer.) Therefore, the next application that
deals with the double-click event topic in the GWT will provide much less capability, (with
quite a bit more code), than this simple application in standard Java.
GwtApp023 – Handling double-click events in
the GWT
As near as I have been able to determine, the only way to identify double-click
events in the GWT is through the use of an EventPreview listener object
as described in the earlier applications in this lesson.
The basic problem
|
The basic problem is illustrated by the text in Figure 11, which shows the
time sequence in which information regarding events becomes
available to an event preview object for the case where the user has
double-clicked a Button object. The words on the left in Figure 11
identify the types of events as they occur. You will learn what the words on the right
mean later when I explain this application.
Figure 11. A basic problem in the GWT.
mousedown: passed through focus: passed through mouseup: passed through click: cancelled mouseup: passed through dblclick: handled |
As you can see in Figure 11, performing a single double-click on the button
caused the event preview object to see a sequence of six different individual
events of five different types culminating with the double-click event of
interest.
One line of text per event
Each line of text in Figure 11 shows the output produced by one invocation of
the onEventPreview method that is defined in an object of a class that
implements the EventPreview interface. At the end of each invocation, the method must return either true or false. If the method
returns true, listener objects that are registered for that type of event will
be notified of the event and are free to execute their code. If the method returns false, the event will
be cancelled
at that point and no listener objects will be notified that the event was fired.
An erroneous single-click event is the problem
The problem arises from the time sequence of the two boldface lines in Figure
11. The first boldface line indicates that a single-click event was fired.
The second boldface line indicates that a double-click event was fired.
|
As you can see in Figure 11, when the user performs a double-click, the event preview object is
first notified erroneously that a single-click event has been fired. It isn’t until much
later (after the onEventPreview method has terminated) that the
listener object is notified that the event was actually intended by the user to
be a double-click event. By that point in time, the onClick method
for the erroneous single-click event will already be executing unless the event
was cancelled or delayed in some other manner.
Registered onClick methods may already
be executing
Unless the event-preview listener cancels the erroneous single-click event by returning
false, registered onClick methods will have been notified and will have
begun execution even though the user intended for the event to be handled as a
double-click event rather than a single-click event. Unlike in standard
Java, when those methods execute, there is no obvious way for them to know that
the user intended for the event to be handled as a double-click event instead of
a single-click event. Obviously, the erroneous execution of single-click
event handlers can lead to undesirable results.
Another problem
Another problem that is not obvious in Figure 11 is that even though the
onClick method can’t differentiate between single and double-click events, there is
no onDoubleClick method. The only way that I have found to
handle a double-click event is to execute an onClick method that was
specifically
designed to behave appropriately for double-click events.
Application GUI at startup for GwtApp023
Figure 12 shows the application GUI at startup before any click events have
been fired.
Figure 12. Application GUI at startup for GwtApp023.
The main thing to note about Figure 12 is that both buttons display
upper-case text.
Application GUI after clicking both buttons
Figure 13 shows the GUI after the user has double-clicked the top button and
has single-clicked the bottom button.
Figure 13. Application GUI after clicking both
buttons.
As you will see later, an event handler is registered on the top button that
causes the text to toggle between upper-case and lower case each time the user
double-clicks the top button. The event handler ignores single-click
events. Therefore, performing a single-click on the top button has no
effect on the output.
A very important difference
Unlike the standard Java example shown earlier in Figure 9 and Figure 10,
this event handler is unable to distinguish between single-click events and
double-click events and to execute a different action on the basis of which type
of event was fired. Instead, the event handler is forced to simply ignore
single-click events (the handler method isn’t even executed for the case of single-click
events) and to respond only to double-click events.
An event handler on the bottom button
An event handler is registered on the bottom button in Figure 12 to cause the
text on the button to toggle between upper-case and lower case each time the
button fires a single-click event.
The state of focus of the top button
A focus listener is also registered on the top button to monitor and to display
the current state of focus of that button in the label
that separates the two buttons. For example, Figure 14 shows the result of
repeatedly pressing the tab key until the top button gains the focus.
Figure 14. The state of focus of the top button.
The top button in Figure 14 shows a visual indication of focus, and the label
indicates that the top button has gained the focus.
Why did I write this extra code?
My reasons for writing the code to provide the focus monitoring capability
and to provide the bottom button that responds to single-click events will
become clear later when I explain the code for this application.
Basically, it was done to keep me honest with respect to my handling of
double-click events on the top button.
Description of the application
This application forces a Button to ignore single-click events but
respond to double-click events.
It places two buttons and a label in a VerticalPanel and places the
VerticalPanel in the RootPanel as shown in Figure 12. The top
button in Figure 12 is referred to in the code as buttonA and the bottom button is
referred to as buttonB.
An EventPreview filter
An EventPreview listener is used to filter events on buttonA.
This listener is designed to simply pass events fired by any component other than
buttonA along to their respective event handlers. It examines all events fired by buttonA passing focus
events and keyboard events through unchanged to their respective event handlers.
The filter causes a click event
handler that is registered on buttonA to respond only to double-click
events. It cancels real single-click events on buttonA and
converts double-click events on buttonA into artificial single-click events so that
they will be handled by the single-click handler. (As far as I know,
it is not possible, or at least not easy to create a double-click handler with the GWT.)
Single-click events on buttonB
The other button, buttonB, responds to single-click events. Its
purpose is solely to demonstrate that it is not impacted by the EventPreview
filter that is applied to buttonA.
A focus listener
A focus listener is also registered on buttonA to display the current
focus state of buttonA in the label. The purpose of the focus
listener is solely to demonstrate that the EventPreview filter doesn’t have any
impact on any event types on buttonA other than single-click and
double-click events.
|
Display information on a command-line screen
The application displays information such as that shown in Figure 11 on
a
command-line screen in hosted mode to explain what is happening as the
application executes.
Testing
The application was tested using J2SE 5.0, GWT version 1.2.22, and
jakarta-tomcat-5.0.27 running as a localhost server under WinXP.
Familiar code
The application begins in Listing 17 with a large amount of very familiar
code.
Listing 17. Familiar code.
package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp023 implements EntryPoint{ Button buttonA;//This button handles double-click events Button buttonB;//This button handles single-click events Label label; EventPrevue eventPrevue; public void onModuleLoad(){ //Instantiate a container for two buttons. VerticalPanel panel = new VerticalPanel(); RootPanel.get().add(panel); //Instantiate a Button object. This button will // ignore single-click events and handle only double // click events. buttonA = new Button("A"); panel.add(buttonA); //Register a click listener on buttonA that causes the // text on buttonA to toggle between A and a each time // it is clicked. Note that this handler doesn't know // the difference between single-clicks and double // clicks. However, an event preview object filters // all events on this button and allows it to handle // only double-click events as though they were // single-click events. buttonA.addClickListener( new ClickListener(){ public void onClick(Widget sender){ Button source = (Button)sender; if(source.getText().equals("A")){ source.setText("a"); }else{ source.setText("A"); }//end else //The EventPreview object was removed long // enough for this event to be processed. // Restore it. eventPrevue = new EventPrevue(); DOM.addEventPreview(eventPrevue); }//end onClick }//end constructor );//end addClickListener //==================================================// //Register a FocusListener on buttonA to display the // focus status of buttonA in a label. The purpose is // to demonstrate that focus events on buttonA are not // impacted by the event preview filter on buttonA. label = new Label("Text at startup"); panel.add(label); buttonA.addFocusListener( new FocusListener(){ public void onFocus(Widget sender){ label.setText("Gained Focus"); }//end onFocus //----------------------------------------------// public void onLostFocus(Widget sender){ label.setText("Lost Focus"); }//end onLostFocus }//end constructor );//end addFocusListener //==================================================// //Instantiate another button that will handle single // click events in the normal manner. The purpose of // this button is to demonstrate that the filter in // the event preview applies only to buttonA. buttonB = new Button("B"); panel.add(buttonB); //Register a click listener on the button that will // toggle the text on the face of the button between // B and b each time that it is clicked. buttonB.addClickListener( new ClickListener(){ public void onClick(Widget sender){ Button source = (Button)sender; if(source.getText().equals("B")){ source.setText("b"); }else{ source.setText("B"); }//end else }//end onClick }//end constructor );//end addClickListener //==================================================// |
With the exception of the two statements shown in boldface, all of the code
in Listing 17 should be very familiar to you by now. I will refer back to and
explain the two boldface statements later.
Register an EventPreview filter
Listing 18 uses a static method of the DOM class to register an
EventPreview listener object.
Listing 18. Register an EventPreview filter.
eventPrevue = new EventPrevue(); DOM.addEventPreview(eventPrevue); }//end onModuleLoad method |
This listener object is designed to ignore events fired by any component
other than buttonA. It filters all events fired by buttonA
and causes a registered click event handler to respond only to double-click
events. It accomplishes this by canceling single-click events on
buttonA and converting double-click events into single-click events so that
they will be handled by the single-click event handler.
Beginning of the EventPreview filter code
An inner class from which an object is instantiated and registered in
Listing 18 to filter events on buttonA begins in Listing 19.
Listing 19. Beginning of the EventPreview filter
code.
class EventPrevue implements EventPreview{ public boolean onEventPreview(Event event){ //Make sure the event was fired by buttonA. if(DOM.eventGetTarget(event). equals(buttonA.getElement())){ |
The if statement that begins in Listing 19 is used to make certain
that the event being processed was fired by buttonA. As you will
see later, if it was not fired by buttonA, it will be passed through the
method without modification. For example, events fired by the bottom
button in Figure 14 pass through the method unchanged.
Display on command-line screen
The code in Listing 20 displays the event type on the command-line screen as
shown in Figure 11 unless the type is ONMOUSEMOVE. This code doesn’t
display ONMOUSEMOVE events because they occur in great quantity and quickly fill the screen.
Listing 20. Display on command-line screen.
if(DOM.eventGetType(event) != Event.ONMOUSEMOVE){ System.out.print( DOM.eventGetTypeString(event) + ": "); }//end if |
Note that the code in Listing 20 only displays the left portion of a line of
text shown in Figure 11 and leaves the cursor dangling at that point. The right portion of each line of text will be
display later in the program, and the text that is displayed will depend on the
disposition of the event based on its type.
Process double-click events
The nested if statement in Listing 21 determines if the event is a
double-click event, and if so, processes it in a specific manner.
Listing 21. Process double-click events.
//Determine if the event was a double-click. if(DOM.eventGetType(event) == Event.ONDBLCLICK){ //Temporarily disable the event preview filter. DOM.removeEventPreview(eventPrevue); //Fire a single-click event on buttonA. buttonA.click(); //Display remainder of message in Figure 11. System.out.println("handled"); //Return true or false. return true; |
Temporarily disable the event preview filter
For the case where the event is a double-click event (on buttonA), the
code in Listing 21 begins by temporarily disabling the event preview filter in order to
allow one single-click event to bypass the filter and to processed by
the single-click event handler registered on buttonA in Listing 17.
The event preview filter will be reinstated by the code in that single-click event handler after it completes its
work as shown by the two boldface statements in
Listing 17.
|
Force buttonA to fire a click event
After
temporarily disabling the event preview filter, the code in Listing 21 invokes the
click method on buttonA to cause it to fire a single-click event.
This causes the single-click event handler that was registered on buttonA
in Listing 17 to be executed once as a result of this double-click event. This,
in turn, causes the text on the face of buttonA to toggle between "A" and "a"
each time the user executes a double-click on buttonA.
Display the rest of the message in Figure 11
Then the code in Listing 21 causes the right portion of the last line of text
in Figure 11 to be displayed on the command-line screen.
Return true or false
Finally, the code in Listing 21 returns true. As near as I have been
able to determine, in the case of a
double-click event, it doesn’t matter it returns true or false because nothing normally happens as a result of a double-click event
anyway. In other words, there can’t be any double-click event handlers
that are automatically executed as a result of the filter returning true in the
case of a double-click event.
Not a double-click event
The else clause in Listing 22 shows the code that is executed by the
event preview filter for the case where the event was fired by buttonA
but was not a double-click event
on buttonA.
Listing 22. Not a double-click event.
}else{ if(DOM.eventGetType(event) == Event.ONCLICK){ //Complete the message and cancel single-click // events on buttonA. System.out.println("cancelled"); return false; }else{ //Don't cancel other event types on buttonA. if(DOM.eventGetType(event) != Event.ONMOUSEMOVE){ //Complete the message. System.out.println("passed through"); }//end if return true; }//end else }//end else }//end if return true;//Wasn't buttonA, just ignore it. }//end onEventPreview }//end class EventPrevue }//end class GwtApp023 |
The case of a single-click event
The code in Listing 22 begins by testing to determine if the event was a
single-click event. If so, it displays the right half of the fourth line
of text in Figure 11 and returns false to cancel the event and prevent it
from being delivered to registered click event handlers. Thus,
single-click events on buttonA are cancelled by the event preview filter
and prevented from having any impact on the behavior of the program.
Other event types fired by buttonA
|
If the event was not a double-click event and was not a single-click event,
then it is simply passed through the filter by returning true from the
else clause shown in Italics near the middle of Listing 22. In that case, the line of
text on the command-line screen shown in Figure 11 is completed with the words
"passed through." This is illustrated by focus events and
mouseup events in Figure 11.
Not buttonA
Finally, if the component that fired the event was not buttonA
(buttonB for example), the last return statement in Listing 22 is executed to
return true, causing the event to simply pass through the method and to
be delivered to registered event handlers.
End of class GwtApp023
Listing 22 also signals the end of the code for the class named GwtApp023,
and the end of the discussion of the application having the same name.
Run the programs
I encourage you to copy the code from Listing 23 through Listing 33 into your
text editor, compile it, and execute it. Experiment with it, making changes,
and observing the results of your changes.
Learn how to write web applications using this exciting new technology. Above
all, enjoy the process. Programming can be fun.
Summary
In this lesson, I taught you how to write the Java code necessary to make
effective use of the DOM class in the GWT.
What’s next?
Future lessons will concentrate on the Java programming techniques required
to produce rich Ajax web applications using the GWT framework. This will
include discussions and explanations of such topics as the available GWT user
interface components, possibly some more on event-driven programming using the
GWT, possibly some more on styling, possibly some more on the behavior of drop
targets, and a little about Remote Procedure Calls with the GWT. I may
even try to do a little on the JavaScript Native Interface, (JSNI). At this point,
however, I’m not certain what the order of the topics will be.
Complete program listings
Complete listings of the programs discussed in this lesson are shown in Listing
23 through Listing 33 below.
Listing 23. HTML host page for GwtApp019.
<!-------------------------------------------------------- File GwtApp019.html GWT host page. ---------------------------------------------------------> <html> <head> <title>Wrapper HTML for GwtApp019</title> <meta name='gwt:module' content='GwtApp.GwtApp019'> </head> <!--Assign an ID to the body element to make it accessible by the Java code--> <body id="rootNode"> <script language="javascript" src="gwt.js"></script> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe> <h3>GwtApp019</h3> <!--A paragraph element will be placed here in the output HTML by the Java code--> </body> </html> |
Listing 24. Java code for GwtApp019.
/*File GwtApp019.java The purpose of this app is to demonstrate a very simple operation using the DOM class. Note that an ID attribute is assigned to the body element in the host HTML page to make it accessible to the Java code. The application begins by using a static method of the DOM class to get and save a handle on the root node of the DOM tree (the body element). Then it uses two more static methods of the DOM class to create and populate a new paragraph element. Finally, it uses a static method of the DOM class to append the new node (the new paragraph element) to the DOM tree. Then when the application is executed, the new paragraph element is displayed. Tested using J2SE 5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27 running as a localhost server under WinXP. *********************************************************/ package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; public class GwtApp019 implements EntryPoint{ //This is the entry point method. public void onModuleLoad(){ //Get a handle on the root node of the DOM tree. Element rootNode = DOM.getElementById("rootNode"); //Text to be displayed in the paragraph element that // will be generated using Java code. String para = "This paragraph element was generated " + "by the Java code."; //Create and populate the new paragraph element. Element pElement = DOM.createElement("<p>"); DOM.setInnerText(pElement,para); //Append the new paragraph element to the DOM tree. DOM.appendChild(rootNode,pElement); }//end onModuleLoad method //====================================================// }//end class GwtApp019 |
Listing 25. HTML host page for GwtApp020.
<!-------------------------------------------------------- File GwtApp020.html GWT host page. Revised: 11/26/06 ---------------------------------------------------------> <html> <head> <title>Wrapper HTML for GwtApp020</title> <meta name='gwt:module' content='GwtApp.GwtApp020'> </head> <body> <script language="javascript" src="gwt.js"></script> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe> <h3>GwtApp020</h3> <p>The purpose of this application is to demonstrate the event preview capability of the DOM class.</p> </body> </html> |
Listing 26. Java code for GwtApp020.
/*File GwtApp020.java Copyright 2006 R.G.Baldwin The purpose of this application is to demonstrate the event preview capability of the DOM class. An object of a class that implements the EventPreview interface is registered using a static method of the DOM class to preview all events. When an event is fired, a reference to the event is saved in an instance variable named theEvent. This reference is used later by the onClick method of a ClickListener object registered on a GUI button to determine the state of the Alt key when the click event was fired. Tested using J2SE 5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27 running as a localhost server under WinXP. *********************************************************/ package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp020 implements EntryPoint{ //The contents of this label are modified by the onClick // method when the user clicks a GUI button. Label label = new Label("Startup"); //The following variable is used to store a reference to // each event that is fired. When the GUI button fires // a click event, this reference is used to determine // the state of the Alt key when the user clicked the // GUI button with the mouse. Event theEvent; public void onModuleLoad(){ //Instantiate a new Button object and register a click // listener on it. Button button = new Button("Click Me"); button.addClickListener(new ClickLstnr()); //Use a static method of the DOM class to register an // EventPreview listener object. DOM.addEventPreview(new EventPrevue()); //Add the GUI button and the label to the RootPanel. RootPanel.get().add(button); RootPanel.get().add(label); }//end onModuleLoad method //====================================================// //Inner listener class. An object of this class is // registered on the GUI button. When the user clicks // the GUI button with the mouse, the code in this event // handler uses a static method of the DOM class along // with a reference to the event to determine and // display the state of the Alt key when the event was // fired. The text in the label is set to reflect the // state of the Alt key. class ClickLstnr implements ClickListener{ public void onClick(Widget sender){ if(DOM.eventGetAltKey(theEvent)){ label.setText("Alt key is down."); }else{ label.setText("Alt key is up."); }//end else }//end onClick }//end class ClickLstnr //====================================================// //Inner listener class. An object of this class is // registered using a static method of the DOM class to // preview all events. When an event is fired, a // reference to the event is saved in the instance // variable named theEvent. This reference is used later // by the onClick method to determine and display the // state of the Alt key when the event was fired. The // onEventPreview method returns true to prevent the // event from being cancelled. If it were to return // false, the event would be cancelled and would not be // seen by the ClickListener object that is registered // on the GUI button. class EventPrevue implements EventPreview{ public boolean onEventPreview(Event event){ theEvent = event; return true;//Don't cancel the event. }//end onEventPreview }//end class EventPrevue //====================================================// }//end class GwtApp020 |
Listing 27. HTML host page for GwtApp021.
<!-------------------------------------------------------- File GwtApp021.html GWT host page. ---------------------------------------------------------> <html> <head> <title>Wrapper HTML for GwtApp021</title> <meta name='gwt:module' content='GwtApp.GwtApp021'> </head> <body> <script language="javascript" src="gwt.js"></script> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe> <h3>GwtApp021</h3> <p>The purpose of this application is to demonstrate the ability to determine which mouse button was pressed when a mouse event is fired.</p> </body> </html> |
Listing 28. Java code for GwtApp021.
/*File GwtApp021.java Copyright 2006 R.G.Baldwin The purpose of this application is to demonstrate the ability to determine which mouse button was pressed when a mouse event is fired. An object of a class that implements the EventPreview interface is registered using a static method of the DOM class to preview all events. When an event is fired, a reference to the event is saved in an instance variable named theEvent. This reference is used later by the onMouseDown method of a MouseListener object registered on a GUI inputButton to determine and display which mouse button was pressed. Note that the GUI inputButton is a custom button that knows how to fire mouse events. Tested using J2SE 5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27 running as a localhost server under WinXP. *********************************************************/ package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp021 implements EntryPoint{ //The contents of this label are modified by the // onMouseDown method when the user clicks a GUI // inputButton causing the inputButton to fire a mouse // event. Label outputLabel = new Label("Startup"); //The following variable is used to store a reference // to each event that is fired. When the GUI // inputButton fires a mouse event, this reference is // used to determine which mouse button was pressed. Event theEvent; public void onModuleLoad(){ //Instantiate a new custom button object and register // a mouse listener on it. This custom button knows // how to fire mouse events. Button button = new Button("Mouse Me"); button.setSize("100px","50px"); FocusPanel inputButton = new FocusPanel(button); inputButton.setSize("100px","50px"); //Cause the focus to skip the FocusPanel and go // straight to the button that is wrapped in the // FocusPanel. inputButton.setTabIndex(-1); //Register a mouse listener on the GUI inputButton. inputButton.addMouseListener(new MouseLstnr()); //Use a static method of the DOM class to register an // EventPreview listener object. DOM.addEventPreview(new EventPrevue()); //Add the GUI inputButton and the outputLabel to the // RootPanel. RootPanel.get().add(inputButton); RootPanel.get().add(outputLabel); }//end onModuleLoad method //====================================================// //Inner listener class. An object of this class is // registered on the GUI inputButton. When the user // clicks the GUI inputButton with the mouse, the code // in this event handler uses a static method of the DOM // class along with a reference to the Event object to // determine and display an identification of the mouse // button that was pressed. class MouseLstnr extends MouseListenerAdapter{ public void onMouseDown(Widget sender,int x,int y){ int theMouseButton = DOM.eventGetButton(theEvent); if(theMouseButton == Event.BUTTON_LEFT){ outputLabel.setText("Left Mouse Button"); }else if(theMouseButton == Event.BUTTON_MIDDLE){ outputLabel.setText("Middle Mouse Button"); }else if(theMouseButton == Event.BUTTON_RIGHT){ outputLabel.setText("Right Mouse Button"); }else{ outputLabel.setText("Don't Know"); }//end else }//end onMouseDown }//end class MouseLstnr //====================================================// //Inner listener class. An object of this class is // registered using a static method of the DOM class to // preview all events. When an event is fired, a // reference to the event is saved in the instance // variable named theEvent. This reference is used later // by the onMouseDown method to determine and display // which mouse button was pressed. The onEventPreview // method returns true to prevent the event from being // cancelled. class EventPrevue implements EventPreview{ public boolean onEventPreview(Event event){ theEvent = event; return true;//Don't cancel the event. }//end onEventPreview }//end class EventPrevue //====================================================// }//end class GwtApp021 |
Listing 29. HTML host page for GwtApp022.
<!-------------------------------------------------------- File GwtApp022.html GWT host page ---------------------------------------------------------> <html> <head> <title>Wrapper HTML for GwtApp022</title> <meta name='gwt:module' content='GwtApp.GwtApp022'> </head> <body> <script language="javascript" src="gwt.js"></script> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe> <h3>GwtApp022</h3> <p>The purpose of this App is to use static methods of the DOM class to dynamically control the style of GUI components.</p> </body> </html> |
Listing 30. Java code for GwtApp022.
/*File GwtApp022.java Copyright 2006 R.G.Baldwin The purpose of this application is to use static methods of the DOM class to dynamically control the style of GUI components at runtime. The application instantiates a Button object, uses a static method of the DOM class to set its style to red, and adds it to the root panel. Note that even if you set the color style to #FF0000, it will later be found to have a value of #ff0000. Therefore, any testing that is done on the hexadecimal (when treated as a String) value must use the lower-case representation of the hexadecimal values. Then the application registers a click listener on the button that causes the text on the button to cycle through the colors of red, green, and blue each time the button is clicked. Tested using J2SE 5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27 running as a localhost server under WinXP. *********************************************************/ package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp022 implements EntryPoint{ public void onModuleLoad(){ //Instantiate a Button object, set its style to red, // and add it to the root panel. Button button = new Button("Button"); DOM.setStyleAttribute( button.getElement(),"color","#ff0000"); RootPanel.get().add(button); //Register a click listener on the button that causes // the text on the button to cycle through the colors // red, green, and blue each time the button is // clicked. button.addClickListener( new ClickListener(){ public void onClick(Widget sender){ //Get a reference to the element that // represents the button, and then get the // current value of the color style for that // element. Element element = sender.getElement(); String attr = DOM.getStyleAttribute(element,"color"); //Execute the logic that cycles the color style // through red, green, and blue each time the // button is clicked. if(attr.equals("#ff0000")){ DOM.setStyleAttribute( element,"color","#00ff00"); }else if(attr.equals("#00ff00")){ DOM.setStyleAttribute( element,"color","#0000ff"); }else{ DOM.setStyleAttribute( element,"color","#ff0000"); }//end else }//end onClick }//end constructor );//end addClickListener }//end onModuleLoad method }//end class GwtApp022 |
Listing 31. Java code for DoubleClick01.
/*File DoubleClick01.java Copyright 2006, R.G.Baldwin Illustrates the extreme simplicity of differentiating between single and double-click events on a Button in J2SE 5.0. Tested using J2SE5.0 under WinXP. *********************************************************/ import java.awt.*; import javax.swing.*; import java.awt.event.*; class DoubleClick01 extends JFrame{ public static void main(String[] args){ new DoubleClick01(); }//end main //----------------------------------------------------// Button button = new Button("Click me"); Label label = new Label("Single-click"); DoubleClick01(){ setLayout(new FlowLayout()); add(button); add(label); setSize(250,100); setTitle("Copyright 2006,R.G.Baldwin"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); button.addMouseListener( new MouseAdapter(){ public void mouseClicked(MouseEvent event){ switch(event.getClickCount()){ case 1:label.setText("Single-click");break; case 2:label.setText("Double-click");break; default: label.setText("Don't know"); }//end switch }//end mouseClicked }//end constructor );//end addMouseListener }//end constructor }//end class DoubleClick01 |
Listing 32. HTML host page for GwtApp023.
<!-------------------------------------------------------- File GwtApp023.html GWT host page ---------------------------------------------------------> <html> <head> <title>Wrapper HTML for GwtApp023</title> <meta name='gwt:module' content='GwtApp.GwtApp023'> </head> <body> <script language="javascript" src="gwt.js"></script> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe> <h3>GwtApp023</h3> <p>This application causes a Button to ignore single- click events but respond to double-click events.</p> </body> </html> |
Listing 33. Java code for GwtApp023.
/*File GwtApp023.java Copyright 2006 R.G.Baldwin This application causes a Button to ignore single-click events but respond to double-click events. This application places two buttons and a label in a VerticalPanel and places the VerticalPanel in the RootPanel. One button is referred to as buttonA and the other button is referred to as buttonB. An EventPreview listener is used to filter events on buttonA. This listener is designed to ignore events fired by any component other than buttonA. It filters all events fired by buttonA passing focus events and keyboard events through unchanged. It causes a click event handler that is registered on buttonA to respond only to double-click events. In effect, it cancels single-click events on buttonA but converts double events on buttonA into single- click events so that they will be handled by the single- click handler. As far as it know, it is not possible to create a double-click handler with the GWT. The other button, buttonB, responds to single-click events. Its purpose is simply to demonstrate that it is not impacted by the EventPreview filter that is applied to buttonA. A focus listener is registered on buttonA to display the current focus state of buttonA in the label. The purpose is to demonstrate that the EventPreview filter doesn't have any impact on any event types on buttonA other than single-click events. The application displays information on the command-line screen to explain what is happening as it executes. Tested using J2SE 5.0, GWT version 1.2.22, and jakarta-tomcat-5.0.27 running as a localhost server under WinXP. *********************************************************/ package GwtApp.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.*; import com.google.gwt.user.client.ui.*; public class GwtApp023 implements EntryPoint{ Button buttonA;//This button handles double-click events Button buttonB;//This button handles single-click events Label label; EventPrevue eventPrevue; public void onModuleLoad(){ //Instantiate a container for two buttons. VerticalPanel panel = new VerticalPanel(); RootPanel.get().add(panel); //Instantiate a Button object. This button will // ignore single-click events and handle only double // click events. buttonA = new Button("A"); panel.add(buttonA); //Register a click listener on buttonA that causes the // text on buttonA to toggle between A and a each time // it is clicked. Note that this handler doesn't know // the difference between single-clicks and double // clicks. However, an event preview object filters // all events on this button and allows it to handle // only double-click events. buttonA.addClickListener( new ClickListener(){ public void onClick(Widget sender){ Button source = (Button)sender; if(source.getText().equals("A")){ source.setText("a"); }else{ source.setText("A"); }//end else //The EventPreview object was removed long // enough for this event to be processed. // Restore it. eventPrevue = new EventPrevue(); DOM.addEventPreview(eventPrevue); }//end onClick }//end constructor );//end addClickListener //==================================================// //Register a FocusListener on buttonA to display the // focus status of buttonA in a label. The purpose is // to demonstrate that focus events on buttonA are not // impacted by the event preview filter on buttonA. label = new Label("Text at startup"); panel.add(label); buttonA.addFocusListener( new FocusListener(){ public void onFocus(Widget sender){ label.setText("Gained Focus"); }//end onFocus //----------------------------------------------// public void onLostFocus(Widget sender){ label.setText("Lost Focus"); }//end onLostFocus }//end constructor );//end addFocusListener //==================================================// //Instantiate another button that will handle single // click events in the normal manner. The purpose of // this button is to demonstrate that the filter in // the event preview applies only to buttonA. buttonB = new Button("B"); panel.add(buttonB); //Register a click listener on the button that will // toggle the text on the face of the button between // B and b each time that it is clicked. buttonB.addClickListener( new ClickListener(){ public void onClick(Widget sender){ Button source = (Button)sender; if(source.getText().equals("B")){ source.setText("b"); }else{ source.setText("B"); }//end else }//end onClick }//end constructor );//end addClickListener //==================================================// //Use a static method of the DOM class to register an // EventPreview listener object. This listener object // is designed to ignore events fired by any component // other than buttonA. It filters all events fired by // buttonA and causes a registered click event // handler to respond only to double-click events. In // effect, it cancels single-click events on buttonA // but converts double events into single-click events // so that they will be handled by the single-click // handler. As far as it know, it is not possible to // create a double-click handler. eventPrevue = new EventPrevue(); DOM.addEventPreview(eventPrevue); }//end onModuleLoad method //----------------------------------------------------// //Inner class that filters events on buttonA. See the // description above. class EventPrevue implements EventPreview{ public boolean onEventPreview(Event event){ //Make sure the event was fired by buttonA. if(DOM.eventGetTarget(event). equals(buttonA.getElement())){ //Display the event type on the command-line // screen unless the type is ONMOUSEMOVE. Don't // display ONMOUSEMOVE events because they quickly // fill the screen. This is the beginning of a // message that is completed later. if(DOM.eventGetType(event) != Event.ONMOUSEMOVE){ System.out.print( DOM.eventGetTypeString(event) + ": "); }//end if //Determine if the event was a double-click. if(DOM.eventGetType(event) == Event.ONDBLCLICK){ //The event was a double-click on buttonA. // Disable this event preview to allow one // single-click event to get through the filter. // The event preview will be reinstated by the // single-click event handler after it completes // its work. DOM.removeEventPreview(eventPrevue); //Cause buttonA to fire a single-click event // to cause the single-click event handler // method to be executed as a result of this // double-click event. buttonA.click(); System.out.println("handled");//Complete the msg //Return true or false, it doesn't matter which, // because nothing normally happens as a result // of a double-click event anyway. return true; }else{ if(DOM.eventGetType(event) == Event.ONCLICK){ //Complete the message and cancel single-click // events on buttonA. System.out.println("cancelled"); return false; }else{ //Don't cancel other event types on buttonA. if(DOM.eventGetType(event) != Event.ONMOUSEMOVE){ //Complete the message. System.out.println("passed through"); }//end if return true; }//end else }//end else }//end if return true;//Wasn't buttonA, just ignore it. }//end onEventPreview }//end class EventPrevue //====================================================// }//end class GwtApp023 |
Copyright
Copyright 2007, Richard G. Baldwin. Reproduction in whole or in part in any
form or medium without express written permission from Richard Baldwin is
prohibited.
Download
Resources
- 2550
Creating Ajax web applications using the Google Web Toolkit (GWT) and Java - 2552 Controlling layout in AJAX web applications using the GWT and
Java - 2554 Event driven programming in AJAX using the GWT and Java
- 2556 Focus events, click events, and Drag-and Drop in AJAX using the
GWT and Java - 1636
The Essence of OOP using Java, Member Classes - 1638
The Essence of OOP using Java, Local Classes - 1640
The Essence of OOP using Java, Anonymous Classes - 1642
The Essence of OOP using Java, Nested Top-Level Classes - Google Web Toolkit
Deployment of Web Applications in Jakarta Apache Tomcat 5
Comparing the Google Web Toolkit to Echo2- Getting Started
with Jakarta Tomcat, Servlets, and JSP - GWT API Map –
See the relationships among GWT UI classes. - The Unofficial
Google Wiki - GWT Internals
- An evolving online book on the GWT by Eric Sessoms, also known as vain. - Document Object Model (DOM) – the
W3C website.
About the author
Richard Baldwin is a
college professor (at Austin Community College in Austin, TX) and private
consultant whose primary focus is a combination of Java, C#, and XML. In
addition to the many platform and/or language independent benefits of Java and
C# applications, he believes that a combination of Java, C#, and XML will become
the primary driving force in the delivery of structured information on the Web.
Richard has participated in numerous consulting projects and he
frequently provides onsite training at the high-tech companies located in and
around Austin, Texas. He is the author of Baldwin’s Programming
Tutorials, which have gained a
worldwide following among experienced and aspiring programmers. He has also
published articles in JavaPro magazine.
In addition to his programming expertise, Richard has many years of
practical experience in Digital Signal Processing (DSP). His first job after he
earned his Bachelor’s degree was doing DSP in the Seismic Research Department of
Texas Instruments. (TI is still a world leader in DSP.) In the following
years, he applied his programming and DSP expertise to other interesting areas
including sonar and underwater acoustics.
Richard holds an MSEE degree from Southern Methodist University and has
many years of experience in the application of computer technology to real-world
problems.