MVC(Model View Controller)设计模式在JavaFX中有着比Swing更好的表现方式。它使得程序界面设计和程序逻辑设计完全分开,便于代码的可读性和以后的可维护性。例子:
<?xml version="1.0" encoding="UTF-8"?> <?language javascript?> <?import javafx.scene.text.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import javafx.scene.Scene?> <!-- "id" serves to CSS, "fx:id" serves to controller(java or js) and CSS --> <Scene xmlns:fx="http://javafx.com/fxml" width="300" height="275"> <fx:script source="info.js"/> <GridPane styleClass="grid-pane"> <Text styleClass="welcome-text" text="%welcome" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2"/> <Label text="%userName" GridPane.columnIndex="0" GridPane.rowIndex="1"/> <TextField GridPane.columnIndex="1" GridPane.rowIndex="1"/> <Label text="%password" GridPane.columnIndex="0" GridPane.rowIndex="2"/> <PasswordField GridPane.columnIndex="1" GridPane.rowIndex="2" onAction="#handlePFAction"/> <HBox styleClass="h-box" GridPane.columnIndex="1" GridPane.rowIndex="4"> <Button fx:id="submitButton" text="%signIn" onAction="#handleSubmitButtonAction"/> </HBox> <Text fx:id="actionTarget" GridPane.columnIndex="1" GridPane.rowIndex="6"/> <!-- <gridLinesVisible>true</gridLinesVisible> --> </GridPane> <fx:script> var System = java.lang.System; var message = "this is the end of XML contents"; System.out.println(message); </fx:script> </Scene>
/* applies to the root node of Scene, it can specify global common properties */ .root { -fx-background-image: url("background.jpg"); } .label { -fx-font-size: 12px; -fx-font-weight: bold; -fx-text-fill: #333333; -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 ); } .button { -fx-text-fill: white; -fx-font-family: "Arial Narrow"; -fx-font-weight: bold; -fx-background-color: linear-gradient(#61a2b1, #2A5058); -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5,0,0,1 ); } .button:hover, .button:armed { /* pseudo-classes */ -fx-background-color: linear-gradient(#2A5058, #61a2b1); } .grid-pane { -fx-hgap: 10; -fx-vgap: 10; -fx-alignment: center; -fx-grid-lines-visible: false; -fx-padding: 25 25 10 25; } .h-box { -fx-spacing: 10; -fx-alignment: bottom-right; } .welcome-text { -fx-font-size: 32px; -fx-font-family: "Arial Black"; -fx-fill: #818181; -fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7), 6,0,0,2 ); } #actionTarget { -fx-fill: FIREBRICK; -fx-font-weight: bold; -fx-effect: dropshadow( gaussian, rgba(255,255,255,0.5), 0,0,0,1 ); }
// Provide some necessary infos importClass(java.lang.System); var info = "starts loading of XML file"; System.out.println(info);
# This is a default resource bundle when a searching in getBundle() with the # given locale fails. title=Welcome FXML welcome=Welcome userName=User Name: password=Password: signIn=Sign In actionTarget=Sign in button pressed
# This is a Chinese resource bundle. It is encoded by ISO-8859-1. In this case, # characters that cannot be directly represented in ISO-8859-1 encoding can be # written using Unicode escapes as defined in section 3.3 of The Java\u2122 # Language Specification. title=\u6B22\u8FCEFXML welcome=\u6B22\u8FCE userName=\u7528\u6237\u540D\uFF1A password=\u5BC6\u7801\uFF1A signIn=\u767B\u9646 actionTarget=\u767B\u9646\u6309\u94AE\u88AB\u6309\u4E0B
# This is a en_US resource bundle. title=Welcome FXML welcome=Welcome userName=User Name: password=Password: signIn=Sign In actionTarget=Sign in button pressed
# This is a fr_FR resource bundle. title=Bienvenue FXML welcome=Bienvenue userName=Identifiant: password=Mot de Passe: signIn=Se connecter actionTarget=Bouton appuyé
package loginfxml; import java.net.URL; import java.util.ResourceBundle; import javafx.animation.PauseTransition; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Button; import javafx.scene.text.Text; import javafx.util.Duration; /** * It is often preferable to define more complex application logic in a * compiled, strongly-typed language such as Java. For example, some complex * event handlers and any other application logic. * <p> * It implements an <code>Initializable</code> interface, which defines * <code>an initialize()</code> method. It will be called once on an * implementing controller when the contents of its associated document have * been completely loaded. It allows the implementing class to perform any * necessary post-processing on the content. * * @author HAN * */ public class Controller implements Initializable { // If the controller member fields or methods are private or protected, it // should be annotated so as to be accessible to markup. If they are public, // the javafx.fxml.FXML annotation is not necessary. @FXML private Button submitButton; @FXML private Text actionTarget; private ResourceBundle resources; @FXML private void handlePFAction() { PauseTransition pressTime = new PauseTransition(Duration.millis(220)); pressTime.setOnFinished(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { submitButton.disarm(); submitButton.fire(); } }); submitButton.arm(); pressTime.play(); } @FXML private void handleSubmitButtonAction() { actionTarget.setText(resources.getString("actionTarget")); } @Override public void initialize(URL location, ResourceBundle resources) { System.out.println("location: " + location); System.out.println("resources: " + resources); this.resources = resources; System.out.println("to perform any necessary post-processing on the " + "content, which will be called once when the contents of " + "its associated document have been completely loaded"); // For example, to process lookup() method with the given CSS selector, // which normally in java code should be placed after Stage.show(). Note // that the button defined in FXML can not be invoked in Model java code // file which is proven by my practice. System.out.println("name of submit button: " + submitButton.getText()); System.out.println(submitButton.lookupAll(".button")); Button button = (Button) submitButton.lookup(".button"); button.setText("Sign in"); System.out.println("new name of submit button: " + submitButton.getText()); } }
package loginfxml; import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; public class Model extends Application { public static void main(String[] args) { System.out.println("程序首先执行的入口:" + Arrays.toString(args)); launch(args); } @Override public void start(Stage stage) throws Exception { Locale locale = getCurrentLocale(); FXMLLoader fxmlLoader = new FXMLLoader(); fxmlLoader.setLocation(Model.class.getResource("View.fxml")); ResourceBundle resources = ResourceBundle.getBundle( "loginfxml/MyResources", locale, Model.class.getClassLoader()); fxmlLoader.setResources(resources); fxmlLoader.setController(new Controller()); Scene scene = (Scene) fxmlLoader.load(); scene.getStylesheets().add( Model.class.getResource("login.css").toExternalForm()); stage.setTitle(resources.getString("title")); stage.setScene(scene); stage.setResizable(false); stage.show(); } private Locale getCurrentLocale() { Map<String, String> namedParams = getParameters().getNamed(); String languageParam = namedParams.get("language"); String countryParam = namedParams.get("country"); Locale locale = Locale.getDefault(); if (languageParam != null && languageParam.trim().length() > 0) { if (countryParam != null && countryParam.trim().length() > 0) { locale = new Locale(languageParam.trim(), countryParam.trim()); } else { locale = new Locale(languageParam.trim()); } } return locale; } }
所有资源下载链接:
View.fxml
login.css
info.js
MyResources.properties
MyResources_zh_CN.properties
MyResources_en_US.properties
MyResources_fr_FR.properties
Controller.java
Model.java
background.jpg
运行结果(注:在命令行中设置语言包,或者在你的JNLP文件中设置以便Applet或者WebStart应用):