Model View Controller With S W I N G And J F X - Part 3 -


Thành viên VIP
(Continue of Model View Controller With S W I N G And J F X - Part 2 - )

The ModelLoader API
public ModelLoader(String model) throws Exception
  - model String, the file that contains the Model Description in XML
  - Java Exception (e.g. file not found, nullpointer, etc.)
public ModelLoader(String model, String controller) throws Exception
  - model String, the file that contains the Model Description in XML
  - controller String, name of the Controller
  - Java Exception (e.g. file not found, nullpointer, etc.)
public Object load( ) throws Exception
  - Object The frame in JFrame, or JDialog, or JPanel. Casting is required.
  - Java Exception (e.g. file not found, nullpointer, etc.)
public ArrayList<String> nameList()
  - ArrayList<String> Name List of all J-Components (e.g. JLabel, JButton, etc.)
public HashMap<String, Object> getComponentMap()
  - HashMap<String, Object> Map of all instantiated J-Components. Casting is required.
Application example:
Starting from the View:
   ModelLoader ml = new ModelLoader("C:/joe/model/frame.txt");
   JFrame jf = (JFrame) ml.load();
   MyController mc = new MyController(ml.getComponentMap());
and the MyController
public class MyController {
   public MyController(HashMap<String, Object> Map) { = map;
   private HashMap<String, Object> Map;
   // injection of JComponent Dependency here
Java FX - JFX-
The question is now: Is Java FX better or worse? It's difficult to answer. JFX was designed to compete against ".NET of C#". Therefore a lot of manpower was invested to work with the JFX Project. Whatever you think I show you hereunder the parallel JFX MVC of the SWING FrameMVC developed by myself: the model FrameMVC (see Part 2)

As usual, we need a model which is represented in FXML: frame.xml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<!-- Joe Nartca (C) -->
<AnchorPane id="AnchorPane" fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity"
		  minHeight="-Infinity" minWidth="-Infinity" prefHeight="670.0" prefWidth="380.0"
		  xmlns:fx="" fx:controller="fxmlFrameController">
  <Label fx:id="Lab1" text = "Please click" prefHeight="50.0" prefWidth="100.0"
		 layoutX="10" layoutY="5" />
  <Button fx:id="But1" onAction="#click" text="JFXButton" prefHeight="50.0" prefWidth="100.0"
		 layoutX="90" layoutY="5" />
  <Label fx:id="Lab2" text = "Name:" prefHeight="30.0" prefWidth="100.0"
		 layoutX="10" layoutY="65" />
  <TextField fx:id="TxtF1" prefWidth="250" prefHeight="30.0" onAction="#read"
		 layoutX="90" layoutY="65" />
  <Label text = "This is an IT man in Background" prefHeight="14.0" prefWidth="200.0"
		 layoutX="56" layoutY="195" />
  <Label fx:id="Lab4" text = "ReportArea" prefHeight="14.0" prefWidth="100.0"
		 layoutX="150" layoutY="460" />
  <TextArea fx:id="TxtA1" prefHeight="165.0" prefWidth="350.0"
		 layoutX="15" layoutY="490" />
	   <URL value="@frame.css" />
The supporting pane (here: AnchorPane) must always include the reference to the Controller (here: fxmlFrameController). The meanings of other elements are self-explained (more: HERE.) However you may note all FXML components have an unique id (which is similar to the "name of my XML-Model design). The rest, for example: layoutX/Y = location=x,y etc.

FXML allows you to decorate the appearance with the Cascading Style Sheets (suffix .css) and that could greatly beautify your GUI app. And I did that with this simple frame.css (more about JFX-CSS: click HERE) as following.
/* frame.css */
.root {
	-fx-background-repeat: stretch;
	-fx-background-position: center center;
.button {
/*  -fx-background-color: yellow; */
	-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.6), 5, 0.0 , 0 , 1 );
.text-field {
	-fx-background-color: yellow;
	-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.6), 5, 0.0 , 0 , 1 );
If you uncommentize the line "-fx-background-color: yellow;" the background color of the button cannot be controlled inside the Controller It's fixed or in other words: mutual exclusive.
You may note the .root block that contains 3 instructions for the displaying background of the model. In this case it's the AnchorPane. You can either specify the background of AnchorPane using CSS, or directly in the View (see

The Controller
// JFX
import javafx.scene.text.*;
import javafx.scene.control.*;
import javafx.scene.paint.Color;
import javafx.scene.layout.*;
import javafx.geometry.Insets;
import javafx.fxml.FXML;
// Joe Nartca (c)
public class fxmlFrameController  {
	Button But1;
	TextArea TxtA1;
	TextField TxtF1;
	private boolean on = false;
	public void click( ) {
	  But1.setBackground(new Background(new BackgroundFill(on? Color.YELLOW:Color.LIME,
						 CornerRadii.EMPTY, Insets.EMPTY)));
	  TxtA1.appendText("\nButton was clicked. Color changed to:"+(on?"YELLOW":"GREEN"));
	  on = !on;
	public void read() {
	  TxtA1.appendText("\nName is:"+TxtF1.getText());
	// can be declared as "public" (not recommended).
	// Reason? it can be manipulated from outsider.
	private void initialize() {
	  But1.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY,
	  TxtF1.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY,
When JFX-MVC app is started FXMLLoader loads the FXML-model that also contains the reference to the JFX-Controller (see the keyword fx:controller=...). And the Controller is implicitly instantiated. Then the controller starts to look for the method initialize(). If it found this method (either public, or better: private) it executes the initialization. The default method initialize() needs not to be implemented if there's nothing to be instantiated. In our case we have to initialize the Button But1 while the TextField TxtF1 is done inside the FXML model.

The View
import javafx.scene.layout.*;
import javafx.scene.image.*;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
//import javafx.geometry.Insets;
// Joe Nartca (C)
public class FrameFXML extends Application {
  public void start(Stage stage) throws Exception {
	FXMLLoader fxml = new FXMLLoader(getClass().getResource("frame.fxml"));
	AnchorPane root = fxml.load();
	/* in case of direct implementaion (see frame.css)
	try { // create the background Image
	  BackgroundSize bgSize = new BackgroundSize(280, 240, false, false, false, false);
	  Image img = new Image(new File("AIman.jpg").toURI().toString());
	  root.setBackground(new Background(new BackgroundImage(img, BackgroundRepeat.NO_REPEAT,
					  BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, bgSize)));
	} catch (Exception ex) { }
	stage.setScene(new Scene(root));;
As said, you could "css" the background image with CSS file, too. Uncommentize the background parts and you could see the results for yourself.
- JFX Scene's background is the background of the frame that contains the components (here: AnchorPane). The background is mutual-exclusive between BackgroundColor and BackgroundImage. Meaning: either color or image.
- To position the JFX model relating to the screen you have to work with the Stage. It's similar to SWING JFrame. Example:
Here is the displaying models of Joe-MVC SWING and JFX

(left: JoeMVC, right: JFX-MVC)

The joemvc.jar is the most actual version which includes JFormattedTextField and JPasswordField.


Sửa lần cuối: