Example for Java Swing GUI by XML > Class definition
Class definition
Abstract classes
In XMLPanelEdit, there are 3 abstract classes for generating Swing GUI from XML. They are:
The readXML( ) method of these classes read the XML for the Swing GUI, and place the Java components on JPanel.
In case of XMLFrame_1_0 and XMLDialog_1_0, JPanel is placed on JFrame and JDialog correspondingly.
Please make your Java class as the sub-class of one of these abstract classes.
For example, the main window of this example is the sub-class of XMLFrame_1_0.
Your sub-class need not bother about how to read the XML and where to place the Java components. They are the responsibility of XMLFrame_1_0, but not of your sub-class.
But, as you know, the XML does not describe the functions of Java components on Swing GUI.
For instance, where JButton should be placed and how it appears can be defined in the XML, the XML does not define what happens when the user clicks it.
This is the task of your sub-class.
To make it possible, your sub-class needs to access the child components (such as JButton) on your Swing GUI.
From gui variable, your sub-class can access the child components.
So, all you have to do is:
- Define your class as the sub-class of the abstract class
- Define the function (ActionListener) for the child components on the Swing GUI
The second work can be done by overriding iniParts( ) method in your sub-class.
About readXML( )
As described in the above section, readXML( ) of those abstract classes is responsible for:
- Read the XML for Swing GUI
- Place the child Java components on JPanel
As a result, the Swing GUI can be generated as defined in the XML. And, as long as your class extends one of those abstract classes, you are free from the above 2 tasks.
By the way, you may wonder which XML file will be read by readXML( ). To clarify this question, let's see how readXML( ) method works:
- At the very first stage, readXML( ) detects the Locale of the runtime environment.
- Then, it tries to find the property resource file appropriate for the Locale.
- The path to the XML is specified by xml_url property in the property resource file. And readXML( )
reads this XML.
- Based on the tree structure of the XML, readXML( ) creates the Java components and places them on JPanel.
In the second step, the name of property resource file is determined by the class name of your sub-class. Let's assume that your sub-class is com.foo.gui.Bar and the Locale of the runtime environment is en_US. At first, readXML( ) tries to find:
Note that the file name starts with Bar, which is just the class name of your subclass.
In case that this property resource file is not found, then readXML( ) searches:
If this property resource file is not found, then the default property resource file will be searched. The default property resource file is always:
regardless of the Locale for the runtime environment.
For details about property resource file, please read the related section of Java Tutorial.
When the default property resource file is not found, readXML( ) cannot continue to work and the exception will be thrown. Because you cannot prepare the property resource files for all the Locales in the world, please ensure to prepare the default property resource file for your subclass.
You may wonder where to place the property resource files for your subclass. Please be patient. I'll describe about it in the next page.
By this way, readXML( ) can read the property resource files for the run-time Locale. And, because each property resource file can point the XML for the specific Locale, the Swing GUI suitable for the Locale can be created by readXML( ).
For example, Bar_en.properties may point gui/english_bar.xml, while Bar_ja.properties can point gui/japanese_bar.xml. As a result, different Swing GUI can be shown, based on the Locale of the runtime environment.
After readXML( ) finishes its work, your subclass can access:
- Dictionary for all the child Java components on JPanel
- ResourceBundle which is loaded from the property resource file
The first one can be referred as gui variable, and the second by res variable. These 2 variables are available within your subclass, i.e. your subclass can access them after readXML( ) returns.
For details about the abstract classes, please read the related documentation.
Your first subclass...
You can write your source files by any IDE tools or text editors. In case you use some IDE tool, xmlrun.jar (or xmlrun_try.jar) needs to be found in the CLASSPATH to compile the source files. As for JBuilder, please add xmlrun.jar (or xmlrun_try.jar) to Required Libraries of your project.
Now, let's start to define your first subclass. Please look at the example editor again:
When the user clicks the JButton under JTextArea, the JDialog will pop up:
The XML for this dialog is gui/example_diag.xml. Please explore it by the XML editor. As you see, the message in JTextArea is written in this XML. When the user clicks JButton on this dialog, the dialog closes itself. This is only the function of this dialog. This dialog will be the good starting point. So, your first subclass is the class for this dialog.
Its fully qualified class name is com.oopreserch.example.VerySimpleAbout. Because it is the subclass of JDialog, it should extend:
- com.oopreserch.xml.util.XMLDialog_1_0
The XML will be parsed and Java components will be placed on JPanel within JDialog. This will be done by readXML( ) of XMLDialog_1_0. So, you need not bother about this procedure. Invoking readXML( ) within the constructor is enough. VerySimpleAbout starts as below:
public class VerySimpleAbout extends XMLDialog_1_0{
public VerySimpleAbout() {
// true means the modal dialog.
super(true);
readXML();
}
To implement the function of JButton on this dialog, you need to add ActionListener to it. This means that your source code need to access to JButton of this dialog. And JButton is available in gui variable. So, your code will look like this:
JButton close_b=(JButton)(gui.getGUI("diag_close"));
close_b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
hide();
}
});
Note the parameter of getGUI(String) method is diag_close, which is value.name attribute defined in the XML.
Like this, all the child Java components on Swing GUI can be accessed by their value.name attribute in the XML.
The code fragment just above should be placed in iniParts( ) method. And iniParts( ) should be invoked after readXML( ) within the constructor. Now, the full source code of VerySimpleAbout became:
It is easy, isn't it? Thus, your source code can be almost free from GUI related tasks. And, you need not be familiar with XML, while your Swing GUI is written in XML.
All the source of this example are included under example_src directory of the distribution. So, please examine them.
Actions on JToolBar
Now, let's explore the source of:
- com.oopreserch.example.VerySimpleEditor
, which is the main class of the example. On the North part of BorderLayout of the main JPanel, a series of JButtons are placed on JToolBar. Please note that, in the XML for this GUI, these JButtons are defined as the Actions, rather than JButtons. In other words, Actionss will appear as JButtons on JToolBar. And, your subclass can also access these Actions through gui. You can find the code fragment like:
new_a=(Action)gui.getAction("new_doc");
within the source of VerySimpleEditor. Then, the Action object retrieved from gui can be embed into JMenu, which results in the same effect as you add JMenuItem into JMenu. In this example, this can be done by:
JMenu f_menu=new JMenu(res.getString("MenuTitle"));
(f_menu.add(new_a)).setText(res.getString("NewMenu"));
(f_menu.add(open_a)).setText(res.getString("OpenMenu"));
(f_menu.add(save_a)).setText(res.getString("SaveMenu"));
Moreover, JButton on JToolBar and its corresponding JMenuItem on JMenu can be toggled (enabled/disabled) at the same time. Because both of them shares the same Action object, just enabling or disabling the shared Action object is enough. It looks like this:
private void modified(){
if(!wasModified){
wasModified=true;
new_a.setEnabled(false);
open_a.setEnabled(false);
save_a.setEnabled(true);
}
}
Through DocumentListener interface, the method above will be invoked when the text on JTextArea is modified by the user. (Note that VerySimpleEditor itself implements DocumentListener interface and can be notified of DocumentEvent.) And this method enables the Action for saving the file and disables the rest of the Actions. The state of the Action will be reflected to the JButton and JMenuItem associated with it.
Then, what is required to define the function of each Action. For example, when the user clicks JButton for opening the file, VerySimpleEditor needs to pop up the dialog for selecting file and should take the appropriate action. How can you implement this? The abstract classes have already been prepared for this task. When the user clicks JButton on JToolBar or selects JMenuItem on JMenu,
- invokeAction(ToolBarEvent tbe)
is invoked. And, all you have to do is to implement it.
Let's look into how this method is defined in VerySimpleEditor:
public void invokeAction(ToolBarEvent tbe){
int act_num=tbe.getNumber();
switch(act_num){
case 1:
newFile();
break;
case 2:
openFile();
break;
case 3:
saveFile();
break;
default:
break;
}
}
The number allocated to ToolBarEvent indicates which JButton is clicked (or which JMenuItem is selected). This number is given to each Action object by readXML( ), in the order on JToolBar. For the first Action on JToolBar, 1 is given. And, for the second Action, 2 is given. And, so on. For example, when the user clicks the left most JButton on JToolBar (or selects corresponding JMenuItem), The number allocated to ToolBarEvent is 1. And your subclass can take the appropriate action.
Thus, you can take the full advantage of the Action object in a very simple way.
And compile it!
Once you write the source of your subclass, it's time to compile it.
The compiled class hierarchy should be placed just under the project directory.
So, please specify your project directory by -d option of javac.
Under example_src directory, you will find the all the source tree of this example.
To compile the source, please move into example_src directory and run the build.sh (or build.bat) script.
Java and all Java-based trademarks and logos are trademarks or registered of Sun Microsystems, Inc. in the United States and other countries.
ALL CONTENTS COPYRIGHT 2002, Jun Inamori. All rights reserved.
Any questions and comments are welcome to
Jun Inamori
.