HƯỚNG DẪN SWING MVC or JFX with FXML?

Joe

Thành viên VIP
21/1/13
2,925
1,312
113
Hi
The time passes and the new corona year leaps over to the 2021. Who knows what could happen. The Corona Wake-up warning call is already more than ONE year old. Gosh, how fast the time flows....

Let's be optimistic and I show you today the revised version SWING MVC (click HERE) and, as usual, the codes are free for private uses. However, you can have the sources if you fulfill ONE of the following conditions:
  • Members of the CDJ Ban Quan Tri (BQT)
  • owner/founder of a Startup
and the license will go to your startup (together with me).

Back to SWING MVC.

Model-View-Control
with
JAVA SWING

Introduction:
Desktop GUI development becomes more and more complex. The development time becomes longer and longer. There are numerous solution proposals, but MVC approach proves itself the best and is generally accepted. With MVC developers are capable to improve the prototyping work and to shorten the software development process. JAVA offers developers JFX or JavaFX model that bases on the MVC framework. Alas, with SWING developers have to go with third-party Software. The most popular SWING MVC is Spring Boot. However Spring Boot is very complex and requires an intensive study. For example, the configuration alone is a very time-consuming procedure. Due to that I've tried to develop a new approach with SWING that leans on JFX concept.

SWING MVC
As mentioned above, Java SWING MVC leans on the JFX model
image_2021-01-04_131234.png
Instead of FXML/CSS plain text files are used (without Cascading Style Sheets) and the syntax resembles the XML syntax, case-sensitive. Nevertheless the JFX principles stay unchanged. Namely:
  • The Model bases on the SWING objects (javax) in plain text with XML-similar syntax. Example: <panel>name=anyName file=componentFile.txt size=400,600 location=400,0</panel> where the element <panel> stands for JPanel.​
  • The View is the main app where the standard method static void main(String[] args) is implemented. Similar to JFX the main() “launches” the JFX app where the start() loads the model with the FXMLLoader(). Here the loader is the SWINGLoader().
  • The Controller is the part where Dependencies are injected or Actions and Events are processed.​

That is all the similarity between JFX and SWING MVC.

Java SWING MVC
I have developed this Java SWING MVC in order to simplified and to reduce the complexity of MVC development process. To do that I focus on the active GUI SWING objects whereas JFrame, JPanel and JDialog are the main supporting frame (base) for the other SWING objects (JButton, JLabel, JTextField, etc.) Some J-Objects, e.g. JFileChooser or JOptionPane, are interactive and therefore so user-dependent that they belong to the Controller implementation part, not to the Model, nor to the View.
SWINGLoaderAPI.png
The controller as the second parameter (see the 3rd and 4th Constructor above) is instantiated by SWING loader and it must exist even if it is empty or unimplemented. By convention it always has at least ONE parameter: HashMap<String, Object>. The Controller third parameter is the passed-by String array. The String model is a file Name where the model descriptions and all dependencies are found (abs. path. Current Directory is taken in case of rel. path).The HashMap contains all instantiated Java SWING objects (e.g. JButton, JTextArea, etc.) The SWING objects) needs only to be “injected” with actions (e.g. Event Listening) or all kinds of dependency and attributes. Note that the names of the SWING objects must be unique.Example:
Java:
public class ProtoController {
/**  Predefined Constructor for Controller
@param map HashMap with String as keys (defined in the model) and Object as values (J Components)
*/
public MyController(HashMap<String, Object> map) {
    ....
}
Programming example. The View: MySWING.java
Code:
import javax.swing.JFrame;
import javax.swing.UIManager;
// SWING Model-View-Controller
import joeapp.mvc.SWINGLoader;
// Joe Nartca (C)
public class MySWING {
   public MySWING( ) throws Exception {
       // load the model MySwing.txt and MyController
       SWINGLoader sl = new SWINGLoader(“MySwing.txt”, “MyController”);
       ((JFrame) ml.load()).setVisible(true);
    }
   public static void main(String... args) throws Exception {
      UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
       new MySWING( );  // start MVC
   }
}
The invocation is java MySWING

The Model which is in plain text (note: <!-- starts a comment and always ends with --!>. Same XML syntax)
The model: mySwing.txt
image_2021-01-04_135149.png

The subfile tree.txt for JTree
Code:
<!-- + for sub-trees follow, - no subtree. –-!>
<Earth:+:Fruits,Species,Trees/>
<Fruits:-:Orange,Banana,Pineapple,lemon/>
<Species:+:Carnivores, Herbivores/>
<Carnivores:+:Birds,Animals,Fishes/>
<Birds:-:Eagle,Hawk,Owl/>
<Animals:-:Lion,Tiger,Hyena/>
<Fishes:-:Shark,Ocra,Piranha/>
<Herbivores:-:Deer,Horse,Elephant/>
<Trees:-:Fir,Maple,sycamore/>
and the GUI
1609763415097.png

The Modeling in plain text

The syntax is simple. There are only some rules as following:
  • Comment starts with <!-- and always ends with --!>
  • <keyword> element_1 …. element_n </keyword>
  • Case sensitive
  • continue in the next lines is allowed
  • JFrame and JDialog must start as the first line. Same for JPanel if it itself serves as the supporting frame.
  • Embedded J Components for another J Component or of an item-list must be declared in a supplement file (same syntax). Example: See above nodes=tree.txt. Each line (plus continuation) must begin with < and is closed by />
  • Between elements and values space should be avoided (e.g. name=anyName).
  • String can be given with/without double quote. However, string with embedded space must be enclosed by double quotes.
  • Values in a chain must be separated by a comma. Spaces between the values should be avoided.
  • The users are responsible for the size and the location for each J Component. AWT tools (such as BorderLayout, GridLayout, etc.) are NOT supported.
  • Customized SWING objects must possess one Constructor without parameter.
All keywords are derived from the SWING component names -without the J- and all in lower case. Example: button for JButton, textfield for JTextField, etc.

Programming with SWING MVC

Model

The model is stored in a plain text file. For the ease of use it's recommended to use the suffix .txt (dot txt) so that it can be edited by any simple editor (e.g. notepad on Windows). The first line must be the JFrame or JDialog line. If JPanel is used as a support pane in your app it must be the first line, too. Other J components can be coded in any order. The important thing is that its size and its location should not overlap each other (see for example: MySwing.txt of page 3). A straightforward coding algorithm. Example:
Code:
<!-- the viewing frame with embedded JDialog --!>
<frame> name=MyFrame title="MVC with JDialog" size=600,600 location=20,20
        close=true resize=false</frame>
<button>name=Start text="Start Dialog" size=100,100 location=230,230 color=yellow</button>
<dialog>name=MyDialog load=dPanel.txt size=500,500 location=0,0 bgimage=RicePaddy.jpg </dialog>
<!-- end of frame --!>
View
The View development is relatively simple if you don't want to insert some extra works before the View is set VISIBLE (see for example: MySWING.java of page 2). The general structure is:
Java:
Import joeapp.mvc.SWINGLoader:
public class MyApp {
    public MyApp(String model, String controller) {  // always expecting 2 parameters
       SWINGLoader sl = new SWINGLoader(model, controller);
       JFrame jf = (JFrame) sl.load();
       … // do some extra works
       jf.setVisible(true);
    }
    public static void main(String... args) {
       … // your initialization works
    }
}
Controller
The controller always has ONE parameter: HashMap<String, Object>. The HashMap contains all instantiated J Components specified in the model file. They are referenced by their declared name (see for example MyController.java of page 3). Inside the controller “Dependencies” are injected (or implemented). Usually they are the Event Listeners. If you are an experienced developer you can implement here all the fancy things you want to do. Note:you have to access the J Components from the map and to cast them to the correct SWING objects you are working with. The accessing keys are the names declared in the model with the element: name=anyName. Example: JButton
Java:
JButton but = (JButton) map.get(“Start_Button”);  // fetch the JButton under the name Start_button
The general structure is
Java:
Import java.util.HashMap;
// Joe Nartca (C)
public class MyController {
    public MyController(HashMap<String, Object> map) {
        JXYZ xyz = (JXYZ) map.get(“MyXYZ”); // e.g. JButton, JTextField, etc.
        … // insert dependency, e.g. addActionListener(e - > { … });
    }
    … // other methods or internal classes invoked/used by Constructor
}
Model-View-Controller in Java SWING

1609764178575.png

The image shows you the coordinates of SWING objects within a view. JFrame and JDialog are relating to the screen coordinates (absolute) while the other SWING coordinates are relating to JFrame/JDialog (ralative). Coordinates SWING Children of JPanel are relating to JPanel. JFrame and JDialog can directly have SWING children (i.e. without JPanel) directly. The layout of all J-component is designed by their sizes and their locations

SWING Elements

As mentioned previously, SWING Object names are used for SWING MVC modeling elements -without the prefix J and in lower case. Example: for JTextArea it's <textarea>. Each Model element contains some attributes that are used by SWINGLoader to instantiate the corresponding J Component. These attributes are categorized in two parts:
  • Mandatory: Mandatory attributes are obligatory and must be present.
  • Optional: Optional attributes are those that can be omitted.
Each chain of items in the supplement file must be embedded between < … />
Note: It's case sensitive. Filename can be without (relative) or with path (absolute). In case of relative path the current user directory is taken as the ROOT for all subsequent files with relative name. Otherwise the root directory is the path of the model file. Only Icon file can be an URL. Another URL case: see JEditorPane and JTextPane.

The following SWING MVC Objects are implemented (note: passive JObjects such as JFileChooser, JOptionPane, etc. are interactive components that usually trigger an user action -hence they belong to the Controller). Note that 3 keywords name, size and location are mandatory.

JFrame
Code:
<frame>name=anyName tittle="anyTitle" size=width, height bgimage=imgFile location=x,y
              resize=false close=false</frame>
optional: bgimage, location (default 0,0 or upper left corner of screen) and resize,
               tittle, close (default: true), nolayout (default true)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • tittle=.....is the tittle of JFrame
  • bgimage=... defines the background image of JFrame. It could be an URL.
  • size=w,h set JFrame with the width=w and the height=h
  • location=x,y positions JFrame at the coordinate x,y on the screen
  • resize=true/false allows JFrame to be resized (true)
  • close=true/false allows JFrame to be closed (true) at the click on the upper right corner of JFrame X
(continue)
 

Attachments

Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
2,925
1,312
113
(cont.)
JPanel
Code:
<panel>name=name size=w,h location=x,y</panel>
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • size=w,h set JPanel with the width=w and the height=h
  • location=x,y positions JPanel at the coordinate x,y relating to JFrame/JDialog
If JPanel must be embedded inside another J Components it must be declared as following and its included J Components are declared in an extra text file (or supplement file.)
Code:
<panel>name=anyName file=modelFile.txt size=w,h location=x,y</panel>
file=... is the file that contains the J Components for THIS JPanel
Example:
Code:
<frame> name=Embedded title="MVC with JFrame -embedded JPanel-" size=800,600 location=20,20
        bgimage=RicePaddy.jpg close=true resize=false</frame>
<panel>name=EmbeddedJPanel file=panel.txt size=400,600 location=400,0</panel>
The file panel.txt:
Code:
<panel> name=pan size=400,500 location=200,0</panel>
<!-- label and button --!>
<label>name=Lab_1 text="Please click", size=100,12 location=10,25</label>
<button>name=But1 text="START" size=100,50 location=90,5 color=yellow</button>
<!-- label and textfield --!>
<label>name=Lab_2 text="Name:", size=100,12 location=10,75</label>
<textfield>name=TxtField text="Your Name" size=250,30 location=90,65 color=yellow</textfield>
JDialog
Code:
<dialog>name=anyName tittle="anyTitle" load=panel.txt size=w,h location=x,y close=false</dialog>
optional: load (panelModel file), tittle, close (default: true)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • tittle=.....is the tittle of JDialog
  • load=... defines loading JPanel for this JDialog
  • size=w,h set JDialog with the width=w and the height=h
  • location=x,y positions JDialog at the coordinate x,y on the screen
  • close=true/false allows JDialog to be closed (true) at the click on the upper right corner of JDialog X

JTabbedPane
Code:
<tabbedpane>name=name tabs=panel_1.txt,...,panel_X.txt tabtext="text_1",...,"text_X"
            size=w,h location=x,y</tabbedpane>
optional: tabs (where panel_X.txt is the loading JPanel for tab_X), tabtext (header for tab_X)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • tabs=.....gives the list of embedded JPanel for each Tab (in sequence 1,2,...x). For the panel_X.txt: see JPanel.
  • tabtext=... a list of Tab names according to the tabs attribute
  • size=w,h set JTabbedPane with the width=w and the height=h
  • location=x,y positions JTabbedPane at the coordinate x,y relating to JFrame/JDialog

JButton
Code:
<button>name=anyName text=anyText size=w,h location=x,y icon=imageFile font=fontName fontSize=n
  fontType=anyType color=anyColor textColor=anyColor</button>
optional: color, textColor, font, fontSize, fontType
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • text=.....is the name on JButton
  • icon=... the Icon image file for JButton
  • color=... is the background color (java.awt.Color) Example: color=blue.
  • textColor=... is the Text Color (see color)
  • font=... is the font. Example: font=Verdana
  • fontSize=... is the font size (a number). Example: fontSize=13
  • fontType=... is the font type. Example: fontType=bold
  • size=w,h set JButton with the width=w and the height=h
  • location=x,y positions JButton at the coordinate x,y relating to JFrame/JPanel/JDialog

JRadioButton
Code:
<radiobutton>name=anyName text=anyText size=w,h location=x,y  font=fontName fontSize=n
  fontType=anyType color=anyColor textColor=anyColor icon=imageFile color=anyColor</radiobutton>
optional: color, textColor, font, fontSize, fontType
Explanation: see JButton

JToggleButton
Code:
<togglebutton>name=anyName text="anyText" size=w,h location=x,y  font=fontName fontSize=n
  fontType=anyType color=anyColor textColor=anyColor icon=imageFile color=anyColor</button>
optional: color, textColor, font, fontSize, fontType
Explanation: see JButton

JLabel
Code:
<label>name=anyName text="anyText" size=w,h location=x,y icon=fName font=fontName fontSize=n
  fontType=anyType color=anyColor textColor=anyColor opaque=true color=anyColor</label>
optional: opaque (default false), color, textColor, font, fontSize, fontType
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • text=.....is the JLabel text
  • icon=... the Icon image file for JLabel
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • opaque=true/false overlaps the background color
  • size=w,h set JLabel with the width=w and the height=h
  • location=x,y positions JLabel at the coordinate x,y relating to JFrame/JPanel/JDialog

JTextField
Code:
<textfield>name=anyName text="anyText" size=w,h location=x,y column=n color=anyColor font=fontName
  fontSize=n fontType=anyType textColor=anyColor</textfield>
optional: text, color, textColor, font, fontSize, fontType
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • text=.....is the JTextField text
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • column=... defines the number of columns
  • size=w,h set JTextField with the width=w and the height=h
  • location=x,y positions JTextField at the coordinate x,y relating to JFrame/JPanel/JDialog

JFormattedTextField
Code:
<formattedtextfield>name=name text="anyText" size=w,h location=x,y  font=fontName
   fontSize=n fontType=anyType textColor=anyColor column=n color=anyColor</formattedtextfield>
optional: text, color, textColor, font, fontSize, fontType
Explanation: see JTextField

JPasswordField
Code:
<passwordfield>name=name text="anyText" size=w,h location=x,y
                          column=n color=anyColor</passwordfield>
optional: text, color
Explanation: see JTextField

JTextArea
Code:
<textarea>name=anyName text="anyText" size=w,h location=x,y edit=false font=fontName
   fontSize=n fontType=anyType textColor=anyColor column=n color=anyColor row=n
   column=n color=anyColor</textarea>
optional: text, color, row, column, edit (default true), textColor, font, fontSize, fontType
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • text=.....is the JTextArea text
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • column=... gives the number of columns
  • rows=... gives the number of rows
  • edit=true/false is either editable (true) or not.
  • size=w,h set JTextArea with the width=w and the height=h
  • location=x,y positions JTextArea at the coordinate x,y relating to JFrame/JPanel/JDialog

JTextPane and JEditorPane
Code:
<textpane>name=anyName content=plain/html size=w,h location=x,y text=text.txt font=fontName
   fontSize=n fontType=anyType textColor=anyColor</textpane>
<editorpane>name=anyName content=plain/html size=w,h location=x,y text=text.txt font=fontName
   fontSize=n fontType=anyType textColor=anyColor</editorpane>
optinal: content (support: plain or html), text (the file contains the content) or an URL,
         textColor, font, fontSize, fontType
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • text=.....is the content text for JTextPane or JEditorPane. If it's a web URL the content of this site will be downloaded into the pane
  • content=... defines the content format. Either plain or html
  • size=w,h set JTextPane or JEditorPane with the width=w and the height=h
  • location=x,y positions JTextPane/JEditorPane at the coordinate x,y relating to JFrame/ JPanel/JDialog

JList
Code:
<list>name="name" items="string_1",..,"string_x" color="color" size=w.h location=x,y</list>
<list>name="name" items=file.txt color="color" size=w.h location=x,y</list>
optional: items, color
note: only String or icon-file (.gif, .png, .jpg) as items. Other things must be set by controller with add(item)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • items=.....is the item-list or a file.txt that contains the list
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • size=w,h set JList with the width=w and the height=h
  • location=x,y positions JList at the coordinate x,y relating to JFrame/JPanel/JDialog

JComboBox
Code:
<combobox>name=anyName items="string1",..,"stringX" color=anyColor size=w.h location=x,y
  font=fontName fontSize=n fontType=anyType textColor=anyColor </combobox>
optional: items, color, textColor, font, fontSize, fontType
only String or icon-file (.gif, .png, .jpg) as items. Other things must be set by controller with add(item)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • items=.....is the list of items of a file.txt containing the items
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • size=w,h set JComboBox with the width=w and the height=h
  • location=x,y positions JComboBox at the coordinate x,y relating to JFrame/JPanel/ JDialog

JCheckBox
Code:
<checkbox>name=anyName text="text" icon=imagefile selicon=imagefile disicon=imagefile
                   selected=true color=anyColor size=w,h location=x,y</checkbox>
optional: color, selected, selicon, disicon
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • text=... the text for JCheckBox
  • icon=.....the icon image file
  • selicon=... icon if selected
  • disicon=... icon if disselected
  • selected=true/false (default: false) preset selection
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • size=w,h set JCheckBox with the width=w and the height=h
  • location=x,y positions JCheckBox at the coordinate x,y relating to JFrame/JPanel/ JDialog

JProgressBar and JSlider
Code:
<slider>name=anyName size=w,h location=x,y minmax=a,b orient=vertical/horizontal</slider>
<progressbar>name=anyName size=w,h location=x,y minmax=a,b orient=vertical/horizontal</progressbar>
optional minmax, orient (default horizontal)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • minmax=... the min and max value for JProgressBar
  • orient=vertical/horizontal
  • size=w,h set JProgressBar with the width=w and the height=h
  • location=x,y positions JProgressBar at the coordinate x,y relating to JFrame/JPanel/ JDialog

JTable
Code:
<table>name=anyName size=w,h location=x,y roco=n,m color=anyColor table=table.txt</table>
optional roco, table, color
Note: Vector and TableModel are NOT supported. Only String for Object. Format for table.txt
      <col_1,..,col_x/>
      <row_1_1,..,row_1_x/>
      ...
      <row_x_1,..,row_x_x/>
Where col_1 ... col_x must be the first line
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • roco=... gives the number of rows and columns
  • table=.....the file that contains the table
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • size=w,h set JTable with the width=w and the height=h
  • location=x,y positions JTable at the coordinate x,y relating to JFrame/JPanel/JDialog

JTree
Code:
<tree>name=anyName nodes=tree.txt size=w.h location=x,y color=anyColor</tree>
optional: items, color
note: only list of String as nodes or a tree file containing the nodes (currently NO icon)
      format:
      <Root:?:node_1, ... ,node_n/>
      <node_1:?X:item_1 ... node_1:item_X/>
      ...
      <node_n:?:item_1 ... node_n:item_X/>
Where ? stands for + (subtrees follow), - (no substree)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • nodes=.....the file that contains the nodes
  • color=... is the color as a text given by java.awt.Color. Example: color=blue.
  • size=w,h set JTree with the width=w and the height=h
  • location=x,y positions JTree at the coordinate x,y relating to JFrame/JPanel/JDialog

JFXPanel (connection to JFX components)
Code:
<fxpanel>name=anyName size=w,h location=x,y </fxpanel>
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • size=w,h set JFXPanel with the width=w and the height=h
  • location=x,y positions JFXPanel at the coordinate x,y relating to Jframe/JPanel/JDialog

JMenuBar
Code:
<menubar>name=anyName size=w,h location=x,y file=menu.txt</menubar>
obligatory: name, size, location, file
optional: -
note: menu.txt format
      menu:anyName,keyEvent,item:anyName,keyEvent,item:anyName,keyEvent ...
      ...
      menu:anyName,keyEvent,checkbox:anyName,keyEvent (e.g. VK_F)
Continue in the next line with a + after the last item (separated by a blank)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • file=.....the file that contains the menu
  • size=w,h set JMenuBar with the width=w and the height=h
  • location=x,y positions JMenuBar at the coordinate x,y relating to JFrame/JPanel/JDialog

JPopupMenu
Code:
<popupmenu>name=anyName text=anyText size=w,h location=x,y file=items.txt</popupmenu>
obligatory: name, size, location, file
optional: text
Note: items.txt contains the menu items either in text strings or in image-file
      example: "Item_1",image.jpg,...
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • file=...a file contains the list of items
  • text=.....the text for JPopupMenu
  • size=w,h set JPopupMenu with the width=w and the height=h
  • location=x,y positions JPopupMenu at the coordinate x,y relating to JFrame/JPanel/ JDialog

JToolBar
Code:
<toolbar>name=anyName text=anyText orientation size=w,h location=x,y </toolbar>
optinal: text, orientation (HORIZONTAL/VERTICAL)
Explanation:
  • name=... is name to be accessed from HashMap by this name
  • text=.....the text for JToolBar
  • size=w,h set JToolBar with the width=w and the height=h
  • location=x,y positions JToolBar at the coordinate x,y relating to JFrame/JPanel/JDialog
Note: JToolBar is normally populated with different GUI items such as JButton, JComboBox, etc. Because of numerous possibilities JToolBar should be populated in the controller.

Some hints for JComboBox, JList, J Table and JTree: if icons (and text) are used as items the entry format is as following:
Code:
text@imageFile or @imageFile if text is unnecessary
text@URL the URL could be a link to an image on the WEB (Note: only for Image).
Example:
- For JTree: The node (here: Fruits) stands before the item list. The mnemonic + (plus) for the subnodes that follow
             and - (minus) indicates that items follow
<Fruits:-:smiling@smiling.gif,surprise@surprise.gif,thumbup@thumbUp.gif/>

- For JComboBox or JList:
<smiling@smiling.gif,surprise@surprise.gif,thumpup@thumbUp.gif/>
And the displaying results:

Icons_1s.jpgIcons_2s.jpg
 
Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
2,925
1,312
113
(cont.)
SWINGLoader

SWINGLoader works similarly to FXMLLoader. With the descriptions SWINGLoader is able to create and to instantiate the specified J Objects and stores their references in the HashMap. With their unique name (or ID in FXML) J Components can be easily accessed and processed. And that is the way how a controller works. Instead of annotation like @FXML for each component or each method SWING controller can access directly to any J Component by its name by HashMap.get(name). And that eases the correction work during the development phase. Developers can focus either on the model (in plain text) or on the controller. Adding of some new Listeners to a SWING object can be done instantly inside the controller.

SWINGLoader is the parser and the compiler in one. It reads the file model.txt, parses the content and checks it for the syntactic correctness before it compiles the pseudo-codes into Java Codes. Exceptions are thrown only during the runtime. For simplicity the generic Exception class is used to issue the confronted problem as clear as possible. Example: reading a list of item from the JMenuBar.
Java:
    String file = SWING.getItem("file=", s);
    if (file == null) throw new Exception("Expected file=... @line:"+s);
    String[] M = getArray(SWING.getFile(file));
    …
   public static ArrayList<String> getFile(String file) throws Exception {
      File fm = new File(file);
      if (!fm.exists()) throw new Exception("Invalid file: "+file);
      String mod[] = (new String(Files.readAllBytes(fm.toPath()))).split(System.lineSeparator());
       …
   }
The jar-file of SWINGLoader (joemvc.jar) has the size of 23 KB. It's relatively small, neat and fast. What you have to do is to include the joemvc.jar into your (global) CLASSPATH.

Note: If you have to include some JFX components into your SWING app JFXPanel must be populated with JFX Components in your Controller. SWINGLoader provides an instantiated JFXPanel. Example:
Java:
public class JFXController {
  public JFXController(HashMap<String, Object> map) {
    JButton but = (JButton) map.get("But");
    but.addActionListener(e -> {
      JFXPanel jfx = (JFXPanel) map.get("jfx");    // retrieve JFXPanel
      Group root = new Group();
      …. // JFX components
      Scene scene = new Scene(root, 500, 500);
      jfx.setScene(scene);
    });
  }
}
The SWINGLoader Package:
SWINGLoaderPackage.png

SWING API -the tools
SWING_API_tools.png

SWINGLoader API
SWINGLoaderAPI.png

The Renderers API (implicitly used by SWINGLoader to generate the Modeling SWING J components if images are involved as icons. Users shouldn't mess with the Renderers. See next page for details)
Renederer_API.png

Example: JComboBox. Only the content items defines the displaying items (texts or icons). Note: the supplement file icons.txt is here for the clarity.
The model:
Code:
<combobox>name=cBox items="Apple","Orange","Banana","Guava" size=200,30 location=100,320</combobox>
1609941358676.png
Code:
<combobox>name=cBox items=icons.txt size=200,30 location=100,320</combobox>
The icons.txt:
Code:
<smiling@smiling.gif,surprise@surprise.gif,thumpup@thumbUp.gif/>
1609941464111.png

Because you don't deal directly with the Renderers and their ICells your Controller accesses the ICell in dependency of your modeling. Example: by questioning the selected object.
Java:
    JComboBox<String> cbx = (JComboBox) map.get("cBox");
    cbx.addActionListener(e -> {
      Object obj = cbx.getSelectedItem();
      if (obj instanceof ICell) System.out.println("\nYou've selected:"+((ICell)obj).getText());
      else System.out.println("\nYou've selected:"+(String)obj);
    });
Note: the item “text@imageFile” could be “text@https://image.com/smiling.gif”. However, you shouldn't use this case frequently because of the long “downloading time”. In other words: it slowdowns your app. It's better to use the local image files. Similar to JComboBox it's the same with JTree, JTable and JList.

If you work with Renderer your items are wrapped by ICell and when an item is selected its values can be accessed by ICell gettters. All Renderers have ONE method, getICell(), and this method returns the corresponding ICell of the selected cell.
ICellAPI.png

Example:
Java:
    JList<String> jlst = (JList) map.get("jlist");
    jlst.addListSelectionListener(e -> {
      Object obj = jlst.getSelectedValue();
      if (obj instanceof ICell) System.out.println("\nSelected from JList::"+((ICell)obj).getText());
      else  System.out.println("\nSelected from JList::"+(String)obj);
    });
    JTree jtree = (JTree) map.get("jTree");
    jtree.getSelectionModel().addTreeSelectionListener(e -> {
      DefaultMutableTreeNode dn = (DefaultMutableTreeNode)e.getPath().getLastPathComponent();
      ICell ic = (ICell) dn.getUserObject();
      System.out.println("From JTree:"+ic.getText());
    });
Customized SWING objects

For the simplicity SWINGLoader instantiates Customized SWING objects only with empty Constructor (without parameter.) If Parameters are needed they should be worked around with Setters. Example:
Original:
Java:
public class SysMonSWING extends JPanel implements Runnable {
  public SysMonSWING(int width, int height) {
    this.width = width;
    this.height = height;
    setPreferredSize(new Dimension(width, height));
    ax = new ArrayList<Integer>(20);
    mem = new ArrayList<Integer>(20);
    pTi = new ArrayList<Integer>(20);
    pLo = new ArrayList<Integer>(20);
    cpu = new ArrayList<Integer>(20);
    swp = new ArrayList<Integer>(20);
    vir = new ArrayList<Integer>(20);
  }
  ...
Work-Around
Java:
public class SysMonSWING extends JPanel implements Runnable {
  public SysMonSWING( ) {
    super();
  };
  public SysMonSWING(int width, int height) {
    super();
    setLayout(width, height);
  }
  public void setLayout(int width, int height) {
    this.width = width;
    this.height = height;
    setPreferredSize(new Dimension(width, height));
    // create the lists
    ax = new ArrayList<Integer>(20);
    mem = new ArrayList<Integer>(20);
    pTi = new ArrayList<Integer>(20);
    pLo = new ArrayList<Integer>(20);
    cpu = new ArrayList<Integer>(20);
    swp = new ArrayList<Integer>(20);
    vir = new ArrayList<Integer>(20);
  }
  ...
And the declaration in the model for this customized JPanel is as usual:
Code:
<SysMonSWING> name=sysmon size=500,500 location=80,7 </SysMonSWING>
Problems and Exceptions

All SWINGLoader exceptions are thrown by JAVA. The exceptions are usually:

Mistyping of file name of the model or its subfiles. Example: genericPane.txt: missing l from genericPanel.txt
Exception_1.png

Missing a mandatory element (syntax). Example: name=anyName
Code:
<panel> file=genericPanel.txt size=400,600 location=400,0</panel>
C:\JoeApp\mvc\example>java GenericView
Exception in thread "main" java.lang.Exception: Missing name=... @line:<panel> file=genericPanel.txt
size=400,600 location=400,0 </panel>
at joeapp.mvc.SWING.validate(Unknown Source)
….

Syntax problems. Example: missing the closed element </table>
Code:
<table>name=jTable size=170,95 location=200,425 table=tableX.txt color=lightgray
Code:
C:\JoeApp\mvc\example>java GenericView
Exception in thread "main" java.lang.Exception: Missing "</table>" @line:<table>name=jTable size=170,95 location=200,425 table=tableX.txt color=lightgray
        at joeapp.mvc.SWING.validate(Unknown Source)
        ….
The more the coding problems are the vaguer the exceptions would be. As you see the first example (mistyping file name) the exception is a NullPointerException. It's difficult to be exact by such problems because such an exception could be an uninstantiated object (e.g. String) or whatever. Further, SWINGLoader considers the root is the directory where the model is. Two scenarios: the root is

  • either the directory of the model file when it's given with the absolute path,
  • or the working directory (user.dir) when it's a relative path. NullPointerExeption is here the biggest headache.
Missing root in case of embedded SWINGLoader. Example: JFrame invokes JDialog and the JDialog model is with relative path. And the Exception message is, of course, misleading
Java:
    JButton start  = (JButton) map.get("Start");
    start.addActionListener(e -> {
      try {
        SWINGLoader ml = new SWINGLoader("jdialog.txt");
        JDialog jd = (JDialog) ml.load();
        ...
    });
Code:
C:\JoeApp\mvc\example>java DirectMVC
java.lang.Exception: Model must start with <frame> or <panel> or <dialog>.
Found:jdialog.txt
        at joeapp.mvc.SWINGLoader.load(Unknown Source)
        ….
The confusing message is due to the using of the FIRST SWINGLoader constructor which is used to run embedded SWINGLoader and that means: its root is independent from root of the calling SWINGLoader. It works if the jdialog file is given by absolute path. Example
Java:
    JButton start  = (JButton) map.get("Start");
    start.addActionListener(e -> {
      try {
        SWINGLoader ml = new SWINGLoader("c:/JoeApp/mvc/example/model/jdialog.txt");
        JDialog jd = (JDialog) ml.load();
        ...
    });
More: compare the examples between DialogMVC and DirectMVC (the last 2 examples) to see how to work with the embedded SWINGLoader.

Wrong referenced name: The NullPointerException could be arisen if the referenced name is mistyping or unknown (returned NULL by HashMap). Example (declared as “Start” in the model)

Java:
    JButton start  = (JButton) map.get("Button");
    start.addActionListener(e -> {
        ...
    });
Code:
C:\JoeApp\mvc\example>java DirectMVC
java.lang.NullPointerException
        at DirectController.<init>(Unknown Source)
        ….
Same NullPointerException if the starting model is unknown. Example:
Code:
C:\JoeApp\mvc\example>java GenericView jfx.txt JFXController
Exception in thread "main" java.lang.NullPointerException
        at joeapp.mvc.SWING.readJAR(Unknown Source)
Correct is: c:\JoeApp\mvc\example\model\jfx.txt


An Application: this simple “SWING MVC” application ProtoTyping allows you to design and to shape a model interactively. An IDE if you so will. The GUI appearance:
1609942704743.png

It's the SWING MVC Editor that allows the users to prototype a model and to view it without having to create an according Controller in advance. With the JCombobox the users need only to pick the desired SWING objects as they want to have. And then they need only to tailor the SWING objects according to their planed layout. Example:
Code:
<button>name=anyName text=anyText size=w,h location=x,y icon=imageFile color=anyColor textColor=anyColor font=Arial fontType=PLAIN fontSize=s</button>
-----------------modify to your own need---------------------------------------------
<button>name=new text=New size=150,45 location=20,80 font=Verdana
        fontType=BOLD fontSize=14 icon=new.png</button>
And the result is the button New with the font Verdana, bold, size 14 together with the icon new.png (see image above). As you see on the editing panel (here: JTextPane) the keywords (e.g. frame, tabbedpane) are in red, the mandatory words (name, size, location) are in blue and the optional words are in magenta (text, icon, etc.). The buttons are self-explained. If the loaded model (Load button) is valid (Check button) it can be “showed” (Show button) without having to create an empty controller (see the inner image.)
 
Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
2,925
1,312
113
(cont.)
The Prototyping models:
Code:
The main model _prototype_.txt

<frame> name=frame title="ProtoTyping with SWINGLoader" size=900,720 location=10,10 
        close=true resize=false</frame>
<menubar>name=menubar size=862,20 location=10,5 file=_menu_.txt</menubar>
<button>name=new text=New size=150,45 location=20,80 font=Verdana
        fontType=BOLD fontSize=14 icon=new.png</button>
<button>name=load text=Load size=150,45 location=20,130 font=Verdana
        fontType=BOLD fontSize=14 icon=load.png</button>
<button>name=save text=Save size=150,45 location=20,180 font=Verdana
        fontType=BOLD fontSize=14 icon=save.png</button>
<button>name=search text=Search size=150,45 location=20,230 font=Verdana
        fontType=BOLD fontSize=14 icon=search.png</button>
<button>name=replace text=Replace size=150,45 location=20,280 font=Verdana
        fontType=BOLD fontSize=14 icon=replace.png</button>
<button>name=check text=Check size=150,45 location=20,330 font=Verdana
        fontType=BOLD fontSize=14 icon=check.png</button>
<button>name=show text=Show size=150,45 location=20,380 font=Verdana
        fontType=BOLD fontSize=14 icon=show.png</button>
<button>name=undo text=Undo size=150,45 location=20,430 font=Verdana
        fontType=BOLD fontSize=14 icon=undo.png</button>
<button>name=redo text=Redo size=150,45 location=20,480 font=Verdana
        fontType=BOLD fontSize=14 icon=redo.png</button>
<button>name=clear text=Clear size=150,45 location=20,530 textColor=red
        font=Verdana fontType=BOLD fontSize=14 icon=clear.png</button>
<combobox>name=cBox items=_protolist_.txt size=150,45 location=20,580
        font=Verdana fontType=BOLD fontSize=12</combobox>
<tabbedpane>name=tabbed size=685,630 location=180,30 tabs=_tab1_.txt tabtext="New_Model"
        color=gray</tabbedpane>
Code:
The _tab1_.txt for the Tab

<textpane>name=area color=gray size=685,600 location=0,0</textpane>
Code:
The _menu_.txt for the JMenuBar

<menu:New,VK_N,item:Load,VK_L,item:Save,VK_S/>
<menu:Process,VK_P,item:Find,VK_F,item:Replace,VK_R/>
Code:
The _protolist_.txt for the JComboBox

<frame,panel,dialog,button,radiobutton,togglebutton,label,
combobox,checkbox,slider,progressbar,table,tree,fxpanel,textfield,
formattedtextfield,passwordfield,textarea,textpane,editorpane,
tabbedpane,list,toolbar/>

Some Examples

Three following examples show you how SWING MVC works.

A generic View of SWING objects.

GenericView.java
Java:
import javax.swing.*;
// SWING MVC
import joeapp.mvc.SWINGLoader;
// Joe Nartca (C)
public class GenericView {
  public GenericView(String[] p) throws Exception {
    SWINGLoader ml = new SWINGLoader(p[0], p[1]);
    ((JFrame) ml.load()).setVisible(true);
  }
  private static String[] parms;
  public static void main(String... a)  throws Exception {
    if (a.length == 2) parms = a;
    else {
      parms = new String[2];
      parms[0] = "generic.txt";
      parms[1] = "GenericController";
    }
    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    new GenericView(parms);
  }
}
The invocation is simple: java GenericView model.txt controllerName

The model for ALL available J Components: generic.txt
Code:
<frame> name=Embedded title="MVC with JFrame -embedded JPanel-" size=800,600 location=20,20 
        bgimage=RicePaddy.jpg close=true resize=false</frame>
<panel>name=EmbeddedJPanel file=genericPanel.txt size=400,600 location=400,0</panel>
The genericPanel.txt
<panel> name=pan size=500,600 location=200,0</panel>
<label>name=Lab1 text="Please click", size=100,12 location=10,25</label>
<button>name=But1 text="MVCbutton" size=100,50 location=90,5 color=yellow</button>
<progressbar>name=pBar size=180,30 location=195,15 minmax=0,100 orient=horizontal</progressbar>
<label>name=Lab2 text="Name:", size=100,12 location=10,75</label>
<textfield>name=TxtF1 text="Your Name" size=250,30 location=90,65 color=yellow</textfield>
<label>name=Lab3 text="ReportArea", size=100,12 location=10,100</label>
<textarea>name=TxtA1 text="No Report" size=360,200 location=10,120 scroll=true</textarea>
<label>name=Lab4 text="Make a choice", size=100,12 location=10,330</label>
<combobox>name=cBox items="Apple","Orange","Banana","Guava" size=200,30 location=100,320</combobox>
<label>name=Lab5 text="Make a check", size=100,12 location=10,360</label>
<checkbox>name=kBox1 text="Ripe" color=red selected=true size=50,30 location=100,352</checkbox>
<checkbox>name=kBox2 text="Green" color=green size=60,30 location=160,352</checkbox>
<checkbox>name=kBox3 text="Never mind" color=yellow size=100,30 location=235,352</checkbox>
<label>name=Lab6 text="Please push", size=100,12 location=10,395</label>
<radiobutton>name=Radio1 text="push" size=100,50 location=100,375 color=red</radiobutton>
<togglebutton>name=toggle1 text="Toggle" size=100,40 location=160,380 color=red</togglebutton>
<list>name=jlist items="Apple","Orange","Banana","Guava" color=green size=80,90 location=10,425</list>
<tree>name=jTree size=90,95 location=100,425 color=cyan nodes="Apple","Orange","Banana"</tree>
<table>name=jTable size=170,95 location=200,425 table=table.txt color=lightgray</table>
The GenericController.java
Java:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
// Joe Nartca (C)
public class GenericController {
  public GenericController(HashMap<String, Object> map) {
    // get JButton, JTextField and JTextArea
    JButton but = (JButton) map.get("But1");
    JTextField jtf = (JTextField) map.get("TxtF1");    
    JTextArea jta  = (JTextArea) map.get("TxtA1");
    but.addActionListener(e -> {
      but.setBackground(on? Color.yellow:Color.green);
      jta.append("\nButton was clicked. Color changed to:"+(on?"YELLOW":"GREEN")+
                 "\nProcessBar starts....");
      on = !on;
      // start pb Thread
      (new Fill((JProgressBar) map.get("pBar"), jta)).start();
    });
    // read JTextField and write into JTextArea
    jtf.addActionListener(e -> {
      jta.append("\nName is:"+jtf.getText());
    });
    JComboBox<String> cbx = (JComboBox) map.get("cBox");
    cbx.addActionListener(e -> {
      jta.append("\nYou've selected:"+(String)cbx.getSelectedItem());
    });
    c1 = true;
    c2 = c3 = false;
    JCheckBox cb1 = (JCheckBox) map.get("kBox1");
    cb1.addItemListener(e -> {
       if (c1) jta.append("\nYour choice: Ripe.");
       c1 = !c1;
       cb1.setForeground(c1?Color.red:Color.blue);
       cb1.setText(c1?"Ripe":"gone");
    });
    JCheckBox cb2 = (JCheckBox) map.get("kBox2");
    cb2.addItemListener(e -> {
       c2 = !c2;
       if (c2) jta.append("\nYour choice: Green.");
       cb2.setForeground(c2?Color.blue:Color.green);
       cb2.setText(c2?"gone":"Green");
    });
    JCheckBox cb3 = (JCheckBox) map.get("kBox3");
    cb3.addItemListener(e -> {
       c3 = !c3;
       if (c3) jta.append("\nYour choice: NeverMind.");
       cb3.setForeground(c3?Color.blue:Color.yellow);
       cb3.setText(c3?"gone":"Yellow");
    });
    JRadioButton rad = (JRadioButton) map.get("Radio1");
    rad.addItemListener(e -> {
       br = !br;
       jta.append("\nYou've "+(!br?"Radio popped":"pushed"));
       rad.setForeground(br?Color.blue:Color.red);
       rad.setText(br?"pop":"push");
    });
    JToggleButton tog = (JToggleButton) map.get("toggle1");
    tog.addItemListener(e -> {
       jta.append("\nYou've Toggled");
       tog.setBackground(tog.isSelected()?Color.red:Color.blue);
    });
    JList<String> jlst = (JList) map.get("jlist");
    jlst.addListSelectionListener(e -> {
      jta.append("\nSelected from JList:"+jlst.getSelectedValue());
    });
    JTree jtree = (JTree) map.get("jTree");
    jtree.getSelectionModel().addTreeSelectionListener(e -> {
      jta.append("\nSelected from JTee:"+e.getPath().toString());
    });
    JTable jtable = (JTable) map.get("jTable");
    jtable.getSelectionModel().addListSelectionListener(e -> {
      int row = jtable.getSelectedRow();
      int col = jtable.getSelectedColumn();
      jta.append("\nSelected from JTable:"+jtable.getValueAt(row, col));
    });
  }
  private class Fill extends Thread {
    public Fill(JProgressBar pb, JTextArea jta) {
      this.jta = jta;
      this.pb = pb;
    }
    private JProgressBar pb;
    private JTextArea jta;
    public void run() {
      try { 
        for (int i = 0; i <= 100; i += 10) { 
          pb.setValue(i); 
          pb.setIndeterminate(false);
          // delay the thread 
          Thread.sleep(400); 
        } 
        jta.append("\nProgressBar is full");
      } catch (Exception ex) {ex.printStackTrace();}
    }
  }
  private boolean on = false, c1, c2, c3, br = false;
}
And the presentation of GenericView
all.png


JTabbedPane: the model tabbed.txt
Code:
<!-- the viewing frame with JTabbedPane from panel model --!>
<frame> name=Jtabs tittle="MVC with JTabbedPane, JPanel and JTree" size=500,500 location=20,20 
        bgimage=RicePaddy.jpg close=true resize=false</frame>
<tabbedpane>name=Tabbed tabs=tab1.txt,tab2.txt,tab3.txt tabtext="Tabbed_1","Tabbed_2","Tabbed_3"
        size=400,400 location=40,15</tabbedpane>
<!-- end of frame --!>
tab1.txt
Code:
<panel> name=Pane1_1 size=400,500 location=200,20 </panel>
<menubar>name=menubar size=400,20 location=0,0 file=menu.txt</menubar>
<tree>name=jTree nodes=tree.txt size=300,300 location=50,25 color=cyan</tree>
<label>name=Lab1 text="Your Selection:-", size=300,12 location=50,330</label>
tab2.txt
Code:
<panel> name=Panel_2 size=400,500 location=200,20 </panel>
<label>name=Lab4 text="Please click", size=100,12 location=10,25</label>
<button>name=But2 text="MVCbutton" size=100,50 location=90,5 color=yellow</button>
<label>name=Lab5 text="Name:", size=100,12 location=10,75</label>
<textfield>name=TxtF2 text="Your Name" size=250,30 location=90,65 color=yellow</textfield>
<label>name=Lab6 text="ReportArea", size=100,12 location=10,100</label>
<textarea>name=TxtA2 text="No Report" size=360,200 location=10,120 scroll=true</textarea>
<label>name=Lab7 text="Make a choice", size=100,12 location=10,330</label>
<combobox>name=cBox items="Apple","Orange","Banana","Guava"
                     size=200,30 location=100,320</combobox>
tab3.txt
Code:
<panel> name=Panel_3 size=400,500 location=200,20 </panel>
<popupmenu>name=Popup text="popup" size=120,80 location=10,10 file=popup.txt</popupmenu>
<editorpane>name=MyEditor content=plain
                      text=https://docs.oracle.com/javase/9/docs/api/javax/swing/JEditorPane.html
                      size=300,300 location=50,30 </editorpane>
menu.txt
Code:
<menu:File,VK_F,item:Open,VK_O,item:Print,VK_P,item:Copy,VK_C/>
<menu:Help,VK_H,checkbox:About,VK_A,item:Search,VK_S/>
popup.txt
Code:
<item:smiling,smiling.gif,item:surprise,surprise.gif,item:thumbup,thumbUp.gif/>
The TabbedController.java
Java:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
//
import joeapp.mvc.*;
// Joe Nartca (C)
public class TabbedController {
  public TabbedController(HashMap<String, Object> map) {
    JPanel jp = (JPanel) map.get("Pane3");
    JTree tree = (JTree) map.get("jTree");
    JLabel lab = (JLabel) map.get("Lab1");
    JPopupMenu pop = (JPopupMenu) map.get("Popup");
    pop.addMouseListener(new MouseListener() {
      public void mouseEntered(MouseEvent e) {
        pop.show(jp , e.getX(), e.getY());  
      }
      public void mouseClicked(MouseEvent e) { }
      public void mouseExited(MouseEvent e) { }
      public void mousePressed(MouseEvent e) { }
      public void mouseReleased(MouseEvent e) { }
    });
    tree.getSelectionModel().addTreeSelectionListener(e -> {
      lab.setText("Your Selection::"+e.getPath().toString());
    });
    // Tab_2
    JButton but2 = (JButton) map.get("But2");
    JTextField jtf2 = (JTextField) map.get("TxtF2");    
    JTextArea jta2  = (JTextArea) map.get("TxtA2");
    but2.addActionListener(e -> {
      but2.setBackground(on2? Color.yellow:Color.green);
      jta2.append("\nButtonTab_2 was clicked. Color changed to:"+(on2?"YELLOW":"GREEN"));
      on2 = !on2;
    });
    // read JTextField and write into JTextArea
    jtf2.addActionListener(e -> {
      jta2.append("\nName is:"+jtf2.getText());
    });
    JComboBox cbx = (JComboBox) map.get("cBox");
    cbx.addActionListener(e -> {
      jta2.append("\nYou've selected:"+(String)cbx.getSelectedItem());
    });
  }
  private boolean on2 = false;
}
And the presentation with the invocation java GenericView tabbed.txt TabbedControllerTab_1

Tab1
tab_1.png
Tab2
tab_2.png
Tab3
tab_3.png

MVC with JDialog

JDialog: JDialog is started (START button). dialog.txt and dPanel.txt
Code:
<frame> name=MyFrame tittle="MVC with JDialog" size=600,600 location=20,20 
        close=true resize=false</frame>
<button>name=Start text="Start Dialog" size=100,100 location=230,230 color=yellow</button>
<dialog>name=MyDialog load=dPanel.txt size=500,500 location=0,0 bgimage=RicePaddy.jpg </dialog>
Code:
<!-- panel for Dialog --!>
<panel> name=Pane1 size=400,400 location=40,25 </panel>
<label>name=Lab1 text="Please click", size=100,12 location=10,25</label>
<button>name=But text="MVCbutton" size=100,50 location=90,5 color=yellow</button>
<label>name=Lab2 text="Name:", size=100,12 location=10,75</label>
<textfield>name=TxtF text="Your Name" size=250,30 location=90,65 color=yellow</textfield>
<label>name=Lab3 text="ReportArea", size=100,12 location=10,100</label>
<textarea>name=TxtA text="No Report" size=360,200 location=10,120 scroll=true</textarea>
<label>name=Lab4 text="Make a choice", size=100,12 location=10,330</label>
<combobox>name=cBox items="Apple","Orange","Banana","Guava"
                     size=200,30 location=100,320</combobox>
<!-- end of pane1--!>
The DialogController.java
Java:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
// Joe Nartca (C)
public class DialogController {
  public DialogController(HashMap<String, Object> map) {
    // get JButton, JTextField and JTextArea
    JButton start  = (JButton) map.get("Start");
    JButton but    = (JButton) map.get("But");
    JTextField jtf = (JTextField) map.get("TxtF");    
    JTextArea jta  = (JTextArea) map.get("TxtA");
    start.addActionListener(e -> {
      JDialog jd = (JDialog) map.get("MyDialog");
      // because location is not given -> setLocationRelativeTo.
      jd.setLocationRelativeTo((JFrame)map.get("MyFrame"));
      jta.append("\nMVC for JDialog started.");
      jd.setVisible(true); 
    });
    
    but.addActionListener(e -> {
      but.setBackground(on? Color.yellow:Color.green);
      jta.append("\nButtonTab_1 was clicked. Color changed to:"+(on?"YELLOW":"GREEN"));
      on = !on;
    });
    // read JTextField and write into JTextArea
    jtf.addActionListener(e -> {
      jta.append("\nName is:"+jtf.getText());
    });
    JComboBox cbx = (JComboBox) map.get("cBox");
    cbx.addActionListener(e -> {
      jta.append("\nYou've selected:"+(String)cbx.getSelectedItem());
    });
  }
  private boolean on = false;
}
Invocation: java GenericView dialog.txt DialogController
jdialog.jpg
 

Joe

Thành viên VIP
21/1/13
2,925
1,312
113
(last part with SWING_MVC Jar for downloading)

Similarity between SWING MVC and JFX MVC

To show you the similarity between the two MVCs two apps which work exactly as the same, but one is developed in SWING MVC with SWING XML (or SXML) and the other in JFX with FXML. It's about the GUI Server for an Object-Oriented Database (OODB)

The main model

SWING MVC with SXML
Code:
<frame> name=frame title="ODBServer" size=680,600 location=10,10
        close=true resize=false</frame>
<tabbedpane>name=Tabbed tabs=_tab1_.txt,_tab2_.txt,_tab3_.txt,_tab4_.txt
        tabtext=AdminManagement,UserMaintenance,ODBMaintenance,SystemMonitoring
        size=680,600 location=0,5</tabbedpane>
JFX with FXML (see the included Tab4 with the customized JFX Object SysMonJFX)
Code:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>

<?import jfx.SysMonJFX?>

<AnchorPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity"
   minHeight="-Infinity" minWidth="-Infinity" prefHeight="550.0" prefWidth="555.0"
   xmlns="http://javafx.com/javafx/9"
   xmlns:fx="http://javafx.com/fxml/1"
   fx:controller="JFXController">
  <children>
    <TabPane fx:id="tabPane"
         tabClosingPolicy="UNAVAILABLE">
      <tabs>
        <Tab fx:id="serverTab" text="AdminManagement">
            <content>
              <fx:include fx:id="Server" source="ServerTab.fxml" />
            </content>
        </Tab>
        <Tab fx:id="userTab" text="UserMaintenance" onSelectionChanged="#event">
            <content>
              <fx:include fx:id="User" source="UserTab.fxml" />
            </content>
        </Tab>
        <Tab fx:id="odbTab" text="ODBMaintenance" onSelectionChanged="#event">
            <content>
              <fx:include fx:id="ODB" source="ODBTab.fxml" />
            </content>
        </Tab>
        <Tab fx:id="moniTab" text="SystemMonitoring">
            <content>
              <VBox fx:id="vbox" alignment="center" spacing="10" >
                <padding><Insets top="5"/></padding>
                <children>
                  <SysMonJFX fx:id="sysmon" width="520.0" height="503.0" />
                </children>
              </VBox>
            </content>
        </Tab>
      </tabs>
    </TabPane>
  </children>
  <stylesheets>
    <URL value="@joe.css" />
  </stylesheets>
</AnchorPane>
The first Tab

SWING MVC with SXML (Tab1)
Code:
<panel> name=Pane1_1 size=680,500 location=0,0 </panel>
<button>name=start text=START size=120,60 location=10,0 color=green</button>
<button>name=stop text=SHUTDOWN size=120,60 location=10,60</button>
<button>name=list text="ODB List" size=120,60 location=10,120</button>
<button>name=workers text="ODB Workers" size=120,60 location=10,180</button>
<button>name=clients text="All Clients" size=120,60 location=10,240</button>
<button>name=keys text=LockedKeyList size=120,60 location=10,300</button>
<button>name=bcast text=BROADCAST size=120,60 location=10,360</button>
<button>name=exit text=EXIT size=120,60 location=10,420 color=red textColor=blue</button>
<textarea>name=area1 color=lightgray size=500,480 location=140,0</textarea>
<label>name=lab text="PING NODE" size=100,30 location=35,480</label>
<combobox>name=ping items=PING size=500,30 location=140,480</combobox>
JFX with FXML (Tab1)
Code:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.ComboBox ?>
<?import javafx.scene.text.Font?>
<?import javafx.geometry.*?>

<AnchorPane fx:id="serverPane" prefHeight="500.0" prefWidth="520.0"
            xmlns="http://javafx.com/javafx/8"
            xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="ServerTab">
   <children>
      <VBox alignment="center" spacing="10" >
          <HBox spacing="10" >
            <padding><Insets top="10" right="10" left="10"/></padding>
            <VBox alignment="center" spacing="6" >
               <children>
                 <Button fx:id="Start" onAction="#start" text="START"
                         prefHeight="50.0" prefWidth="120.0" />
                 <Button fx:id="Shutdown" onAction="#shutdown" text="SHUTDOWN"
                         prefHeight="50.0" prefWidth="120.0" />
                 <Button fx:id="Odblist" onAction="#odblist" text="ODB List"
                         prefHeight="50.0" prefWidth="120.0" />
                 <Button fx:id="Odbworker" onAction="#odbworker" text="ODB Workers"
                         prefHeight="50.0" prefWidth="120.0" />
                 <Button fx:id="Allclients" onAction="#allclients" text="All Clients"
                         prefHeight="50.0" prefWidth="120.0" />
                 <Button fx:id="Lockedkeylist" onAction="#lockedkeylist" text="LockedKeyList"
                         prefHeight="50.0" prefWidth="120.0" />
                 <Button fx:id="Broadcast" onAction="#broadcast" text="BROADCAST"
                         prefHeight="50.0" prefWidth="120.0" />
                 <Button fx:id="Exit" onAction="#exit" text="EXIT"
                         prefHeight="50.0" prefWidth="120.0" />
              </children>
            </VBox>
            <TextArea fx:id="report" prefWidth="405.0"
                      wrapText="true" editable="false"/>
         </HBox>
         <HBox alignment="center"  spacing="5" >
            <Label fx:id="PingLab" text="PING NODE">
                <font>
                  <Font size="13.0" />
                </font>
            </Label>
            <ComboBox fx:id="Pingnode" onAction="#pingnode" promptText="Select a Node"
                      prefHeight="40.0" prefWidth="447.0" />
         </HBox>
      </VBox>
   </children>
</AnchorPane>
The same for Tab2 and Tab3. Tab4 is as following:

SWING MVC with SXML and customized JPanel as SysMonSWING
Code:
<panel>name="panel_4" size=680,500 location=0,0</panel>
<SysMonSWING> name=sysmon size=500,500 location=80,7 </SysMonSWING>
Tab4 of JFX with FXML and customized JFX object as SysMonJFX: see the main FXML file.

The main appearence (Tab1):
SWING_JFX_1s.png
And the Tab4 is similar too:
SWING_JFX_1.png

The appearence of JFX is smoother and more beautiful thanks to the Cascade Style Sheet (css) technique.

Enjoy
cdj.zip contains 48 following files:
  1. joemvc.jar
  2. proto\Modelling.jar
  3. example\DialogController.java
  4. example\DialogMVC.java
  5. example\DirectController.java
  6. example\DirectMVC.java
  7. example\EmbeddedMVC.java
  8. example\frame.css
  9. example\frame.fxml
  10. example\FrameController.java
  11. example\FrameFXML.java
  12. example\FrameMVC.java
  13. example\fxmlFrameController.java
  14. example\GenericController.java
  15. example\GenericView.java
  16. example\JFXController.java
  17. example\PanelController.java
  18. example\PanelMVC.java
  19. example\TabbedController.java
  20. example\TabbedMVC.java
  21. example\model\AIman.jpg
  22. example\model\dialog.txt
  23. example\model\diPanel.txt
  24. example\model\direct.txt
  25. example\model\dPanel.txt
  26. example\model\editorpane.txt
  27. example\model\embedded.txt
  28. example\model\frame.txt
  29. example\model\fruits.txt
  30. example\model\generic.txt
  31. example\model\genericPanel.txt
  32. example\model\icons.txt
  33. example\model\jdialog.txt
  34. example\model\jfx.txt
  35. example\model\menu.txt
  36. example\model\panel.txt
  37. example\model\popup.txt
  38. example\model\RicePaddy.jpg
  39. example\model\smiling.gif
  40. example\model\surprise.gif
  41. example\model\tab1.txt
  42. example\model\tab2.txt
  43. example\model\tab3.txt
  44. example\model\tabbed.txt
  45. example\model\table.txt
  46. example\model\tableX.txt
  47. example\model\thumbUp.gif
  48. example\model\tree.txt

Note: joemvc.jar is the SWING_MVC package and Modelling.jar is the Prototyping application (a simple IDE)
How to install and work with joemvc.jar and Modelling.jar:
  1. unzip cdj.zip to any directory of choice. Example: C:\SWING_MVC and you get 2 subdirectories Proto and example (with its own subdirectory model)
  2. include joemvc.jar into the global CLASSPATH (e.g. WINDOWS: set CLASSPAT=C:\SWING_MVC\joemvc.jar;%CLASSPATH%)
  3. open a CMD window and move to the example directory and create a subdirectory, says classes, and run the compile javac -d ./classes *.java and subdirectory classes will be filled with the compiled examples.
  4. include the subdirectory classes in CLASSPATH (e.g. WINDOWS: set CLASSPATH=.\classes;%CLASSPATH%)
  5. to run the examples:
    Code:
    C:\SWING_MVC\example>java GenericView ./model/tabbed.txt TabbedController
  6. to run the ProtoTyping:
    Code:
     C:\JoeApp\mvc\Proto>java -jar Modelling.jar
 

Attachments

Sửa lần cuối: