MVC设计模式

fearlessMore 2013-08-19 06:21:24
MVC(Model View Controller)设计模式在JavaFX中有着比Swing更好的表现方式。它使得程序界面设计和程序逻辑设计完全分开,便于代码的可读性和以后的可维护性。例子:
<?xml version="1.0" encoding="UTF-8"?>
<?language javascript?>

<?import java.net.*?>
<?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" fx:controller="loginfxml.Controller"
width="300" height="275">
<stylesheets>
<URL value="@login.css"/>
</stylesheets>
<fx:script source="simple_event_handlers.js"/>
<GridPane styleClass="grid_pane">
<Text styleClass="welcome_text" text="Welcome"
GridPane.columnIndex="0" GridPane.rowIndex="0"
GridPane.columnSpan="2" />
<Label text="User Name:"
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="Sign In"
onAction="handleSubmitButtonAction()" />
</HBox>
<Text fx:id="actionTarget"
GridPane.columnIndex="1" GridPane.rowIndex="6" />
<!-- <gridLinesVisible>true</gridLinesVisible> -->
</GridPane>
<fx:script>
importClass(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 );
}
importClass(java.lang.System);

// Convenience methods to define some simple event handlers.
function handleSubmitButtonAction() {
actionTarget.setText("Sign in button pressed");
System.out.println("handled by javascript");
}
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.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 void handlePFAction() {
System.out.println("handled by java");
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();
}

@Override
public void initialize(URL location, ResourceBundle resources) {
System.out.println("location: " + location);
System.out.println("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 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) {
launch(args);
}

@Override
public void start(Stage stage) throws Exception {
Scene scene = FXMLLoader.load(getClass().getResource("View.fxml"));

stage.setTitle("Welcome FXML");
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
}
所有资源下载链接:
View.fxml
login.css
simple_event_handlers.js
Controller.java
Model.java
background.jpg

...全文
1433 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
fearlessMore 2013-08-24
  • 打赏
  • 举报
回复
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.Scene?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.collections.FXCollections?>
<?import addressbook.*?>

<Scene xmlns:fx="http://javafx.com/fxml" fx:controller="addressbook.Controller"
stylesheets="addressbook/addressbook.css">
<GridPane styleClass="grid-pane">
<Label id="address-book" text="%addressBook"
GridPane.columnIndex="0" GridPane.rowIndex="0"/>
<TableView fx:id="tableView" tableMenuButtonVisible="true"
GridPane.columnIndex="0" GridPane.rowIndex="1">
<columns>
<TableColumn fx:id="firstNameColumn"
text="%firstName" prefWidth="100">
<cellValueFactory>
<PropertyValueFactory property="firstName"/>
</cellValueFactory>
<cellFactory>
<FormattedTableCellFactory alignment="CENTER"/>
</cellFactory>
</TableColumn>
<TableColumn
text="%lastName" prefWidth="100">
<cellValueFactory>
<PropertyValueFactory property="lastName"/>
</cellValueFactory>
</TableColumn>
<TableColumn
text="%email" prefWidth="210" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="email"/>
</cellValueFactory>
</TableColumn>
</columns>
<Person firstName="Jacob" lastName="Smith"
email="jacob.smith@example.com"/>
<Person firstName="Isabella" lastName="Johnson"
email="isabella.johnson@example.com"/>
<Person firstName="Ethan" lastName="Williams"
email="ethan.williams@example.com"/>
<Person firstName="Emma" lastName="Jones"
email="emma.jones@example.com"/>
<Person firstName="Michael" lastName="Brown"
email="michael.brown@example.com"/>
<sortOrder>
<fx:reference source="firstNameColumn"/>
</sortOrder>
</TableView>
<HBox styleClass="h-box" GridPane.columnIndex="0" GridPane.rowIndex="2">
<TextField fx:id="firstNameField" promptText="%firstName"
prefWidth="90"/>
<TextField fx:id="lastNameField" promptText="%lastName"
prefWidth="90"/>
<TextField fx:id="emailField" promptText="%email"
prefWidth="150"/>
<Button text="%add" onAction="#addPerson"/>
</HBox>
</GridPane>
</Scene>
.grid-pane {
-fx-alignment: center;
-fx-hgap: 10;
-fx-vgap: 10;
-fx-padding: 10;
}

#address-book {
-fx-font: NORMAL 20 Tahoma;
}

.h-box {
-fx-spacing:10;
-fx-alignment: bottom-right;
}
# Title of window
title=FXML Address Book

# Name of label above the table view
addressBook=Address Book

# Name of the first table column
# & Prompt text of text field for the first table column
firstName=First Name

# Name of the second table column
# & Prompt text of text field for the second table column
lastName=Last Name

# Name of the third table column
# & Prompt text of text field for the third table column
email=Email Address

# Name of button for adding rows to table
add=Add
# Title of window
title=FXML\u5730\u5740\u7C3F

# Name of label above the table view
addressBook=\u5730\u5740\u7C3F

# Name of the first table column
# & Prompt text of text field for the first table column
firstName=\u540D\u5B57

# Name of the second table column
# & Prompt text of text field for the second table column
lastName=\u59D3

# Name of the third table column
# & Prompt text of text field for the third table column
email=\u7535\u5B50\u90AE\u4EF6

# Name of button for adding rows to table
add=\u6DFB\u52A0
package addressbook;

import java.text.Format;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.text.TextAlignment;
import javafx.util.Callback;

public class FormattedTableCellFactory<S, T> implements
Callback<TableColumn<S, T>, TableCell<S, T>> {
private TextAlignment alignment;
private Format format;

public TextAlignment getAlignment() {
return alignment;
}

public Format getFormat() {
return format;
}

public void setAlignment(TextAlignment alignment) {
this.alignment = alignment;
}

public void setFormat(Format format) {
this.format = format;
}

@Override
public TableCell<S, T> call(TableColumn<S, T> arg0) {
final TableCell<S, T> cell = new TableCell<S, T>() {
@Override
protected void updateItem(T item, boolean empty) {
if (item == getItem()) {
return;
}
super.updateItem(item, empty);
if (item == null) {
setText(null);
setGraphic(null);
} else if (item instanceof Node) {
setText(null);
setGraphic((Node) item);
} else if (format != null) {
setText(format.format(item));
setGraphic(null);
} else {
setText(item.toString());
setGraphic(null);
}

/* add a context menu */
addCM(this);
}
};
if (alignment == null) alignment = TextAlignment.LEFT;
cell.setTextAlignment(alignment);
switch (alignment) {
case CENTER:
cell.setAlignment(Pos.CENTER);
break;
case RIGHT:
cell.setAlignment(Pos.CENTER_RIGHT);
break;
default:
cell.setAlignment(Pos.CENTER_LEFT);
}
return cell;
}

private MenuItem delete = new MenuItem("Delete");
private ContextMenu contextMenu = new ContextMenu(delete);

private void addCM(final TableCell<S, T> cell) {
@SuppressWarnings("rawtypes")
final TableRow row = cell.getTableRow();
delete.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
cell.getTableView().getItems().remove(row.getItem());
}
});
if (row != null) {
if (row.getItem() != null) {
row.setContextMenu(contextMenu);
}
}
}
}
package addressbook;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
* A Bean convention based data model.
*
* @author HAN
*/
public class Person {
private StringProperty firstName = new SimpleStringProperty();
private StringProperty lastName = new SimpleStringProperty();
private StringProperty email = new SimpleStringProperty();

public Person() {
this("", "", "");
}

public Person(String firstName, String lastName, String email) {
setFirstName(firstName);
setLastName(lastName);
setEmail(email);
}

public final String getFirstName() {
return firstName.get();
}

public final String getLastName() {
return lastName.get();
}

public final String getEmail() {
return email.get();
}

public final void setFirstName(String firstName) {
this.firstName.set(firstName);
}

public final void setLastName(String lastName) {
this.lastName.set(lastName);
}

public final void setEmail(String email) {
this.email.set(email);
}

public StringProperty firstNameProperty() {
return firstName;
}

public StringProperty lastNameProperty() {
return lastName;
}

public StringProperty emailProperty() {
return email;
}
}
/**
* An address book application.
*
* @author HAN
*/
package addressbook;
package addressbook;

import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;

public class Controller {
@FXML
private TableView<Person> tableView;
@FXML
private TextField firstNameField;
@FXML
private TextField lastNameField;
@FXML
private TextField emailField;

@FXML
private void addPerson() {
tableView.getItems().add(
new Person(firstNameField.getText(), lastNameField.getText(),
emailField.getText()));
firstNameField.clear();
lastNameField.clear();
emailField.clear();
}
}
package addressbook;

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) {
launch(args);
}

@Override
public void start(Stage stage) throws Exception {
Locale locale = getCurrentLocale();
ResourceBundle resources = ResourceBundle
.getBundle("addressbook/addressbook", locale,
Model.class.getClassLoader());
stage.setTitle(resources.getString("title"));
stage.setScene((Scene) FXMLLoader.load(
Model.class.getResource("View.fxml"), resources));
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;
}
}
fearlessMore 2013-08-23
  • 打赏
  • 举报
回复
引用 18 楼 Gaowen_HAN 的回复:
[quote=引用 17 楼 raistlic 的回复:] +1 有些 basic ui 类有明显的设计缺陷,很多东西被硬编码,导致扩展功能比较困难…… SwingLabs (SwingX) 的很多组件都没有加进 JDK …… 据说 SwingApplicationFramework (JSR 296) 曾经试图加进JDK,未果…… 如果有 SwingApplicationFramework 的话,也许至少会帮助初学者写出线程基本正确的Swing程序(由于对Swing线程机制的不理解,很多很多的Swing程序线程都是错的,新手开始写Swing程序极少有人把线程写对。留意过一些培训课程,很多“名师”,甚至专讲Swing入门的课程,里面的线程居然也是错的) Oracle 在UI方面的重心还是放在 JavaFX 上了,Swing基本上是处于维护状态。 Swing 里的 MVC 也许不是很好的学习的例子,因为可以从不同的层面理解……,而有些层面是 M + VC,其中的 VC 就是一些硬编码的ui类 我觉得 Swing 里面最有学习价值的大概是它的单线程机制,因为这种单线程机制是在很多UI框架都通用的知识。 有一篇很老的文章今天也没有过时: https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html
嗯,Swing的线程重要性是绝对的。EDT,main,SwingWorker或者自定义一个线程都可以丰富Swing的开发比如组件动态效果响应等。SwingWorker可以优化Swing编写复杂界面响应慢或无响应的问题。组件的创建在EDT,不要直接在main线程里直接new JFrame()等等。有几个外国权威网站写的关于Swing Thread的写的比较好,英语无障碍的推荐去看一下。[/quote]还想说一点,MVC只是一个设计模式,比如Swing JButton的ButtonUI就是View,ButtonModel就是Model,JButton的一些方法就起到控制的作用。但是Swing的整体设计好像还达不到我上面列举的JavaFX Login程序的MVC模式。这样使得一个Swing程序特别是复杂界面的程序往往比较混杂,不利于可读性和以后的可维护性。
fearlessMore 2013-08-23
  • 打赏
  • 举报
回复
引用 17 楼 raistlic 的回复:
+1 有些 basic ui 类有明显的设计缺陷,很多东西被硬编码,导致扩展功能比较困难…… SwingLabs (SwingX) 的很多组件都没有加进 JDK …… 据说 SwingApplicationFramework (JSR 296) 曾经试图加进JDK,未果…… 如果有 SwingApplicationFramework 的话,也许至少会帮助初学者写出线程基本正确的Swing程序(由于对Swing线程机制的不理解,很多很多的Swing程序线程都是错的,新手开始写Swing程序极少有人把线程写对。留意过一些培训课程,很多“名师”,甚至专讲Swing入门的课程,里面的线程居然也是错的) Oracle 在UI方面的重心还是放在 JavaFX 上了,Swing基本上是处于维护状态。 Swing 里的 MVC 也许不是很好的学习的例子,因为可以从不同的层面理解……,而有些层面是 M + VC,其中的 VC 就是一些硬编码的ui类 我觉得 Swing 里面最有学习价值的大概是它的单线程机制,因为这种单线程机制是在很多UI框架都通用的知识。 有一篇很老的文章今天也没有过时: https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html
嗯,Swing的线程重要性是绝对的。EDT,main,SwingWorker或者自定义一个线程都可以丰富Swing的开发比如组件动态效果响应等。SwingWorker可以优化Swing编写复杂界面响应慢或无响应的问题。组件的创建在EDT,不要直接在main线程里直接new JFrame()等等。有几个外国权威网站写的关于Swing Thread的写的比较好,英语无障碍的推荐去看一下。
raistlic 2013-08-23
  • 打赏
  • 举报
回复
+1 有些 basic ui 类有明显的设计缺陷,很多东西被硬编码,导致扩展功能比较困难…… SwingLabs (SwingX) 的很多组件都没有加进 JDK …… 据说 SwingApplicationFramework (JSR 296) 曾经试图加进JDK,未果…… 如果有 SwingApplicationFramework 的话,也许至少会帮助初学者写出线程基本正确的Swing程序(由于对Swing线程机制的不理解,很多很多的Swing程序线程都是错的,新手开始写Swing程序极少有人把线程写对。留意过一些培训课程,很多“名师”,甚至专讲Swing入门的课程,里面的线程居然也是错的) Oracle 在UI方面的重心还是放在 JavaFX 上了,Swing基本上是处于维护状态。 Swing 里的 MVC 也许不是很好的学习的例子,因为可以从不同的层面理解……,而有些层面是 M + VC,其中的 VC 就是一些硬编码的ui类 我觉得 Swing 里面最有学习价值的大概是它的单线程机制,因为这种单线程机制是在很多UI框架都通用的知识。 有一篇很老的文章今天也没有过时: https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html
valenon 2013-08-21
  • 打赏
  • 举报
回复
java swing要火了
王小北0304 2013-08-21
  • 打赏
  • 举报
回复
fearlessMore 2013-08-21
  • 打赏
  • 举报
回复
运行结果(注:在命令行中设置语言包,或者在你的JNLP文件中设置以便Applet或者WebStart应用):



fearlessMore 2013-08-21
  • 打赏
  • 举报
回复
修改楼主的MVC例子版本:
<?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.
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.
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.
welcome=Welcome
userName=User Name:
password=Password:
signIn=Sign In
actionTarget=Sign in button pressed

# This is a fr_FR resource bundle.
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.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) {
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("Welcome FXML");
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

运行结果(注:在命令行中设置语言包,或者在你的JNLP文件中设置以便Applet或者WebStart应用):



彩虹糖sweet 2013-08-21
  • 打赏
  • 举报
回复
thank you
fearlessMore 2013-08-20
  • 打赏
  • 举报
回复
引用 5 楼 u011626555 的回复:
楼主好牛!狂顶。。。。。向楼主学习
我只是计算机业余爱好者本行做营销的,对编程方面的知识涉及面很窄,只是下班回来后查了查网上资料有感而写的小程序而已。具体开发大项目还从来没做过或者精通java也谈不上。
soar_angel 2013-08-20
  • 打赏
  • 举报
回复
谢谢楼主分享,我之前有个朋友研究html5,好像也很有前途,我现在想转行做java,我想学学java的框架,spring之类的,所以楼主的示例代码可不可以发给我 zhanchigaofei2008@163.com,谢谢
fearlessMore 2013-08-20
  • 打赏
  • 举报
回复
引用 9 楼 soar_angel 的回复:
顶楼主,我也想学习
我用Swing做出的例子:

JavaFX做出的界面:

后来又做出了自己编写的一套基于Synth的L&F,其与直接在代码中重绘某个组件不同,最大优点是具有可插拔性,即在不改变原有程序代码的情况下,用户可以自己选择切换风格,通用性增强。对于前面的JLayer的界面切换成MyLNF后的效果:
(获得焦点效果)

(失去焦点后的效果)

(鼠标移到Container内容面板上后显示的效果)

最后说下自己的感想:
1、现在Java界面编程真的不是首选。可插拔式的Look and feel不论基于Basic还是Metal编写繁琐,开发周期长。后来1.7推出的Synth基于XML导入式概念虽然新颖,但是对于Components Specific Properties的支持不够例如对于JTable的Properties支持很少导致可定制性降低。基于Nimbus编写的话,首先运行效率不如Metal,然后重绘每个Component也很麻烦,用图片做背景需要九宫格技术的支持。无论如何,Look and feel由于Java内部本身的限制,提供定制的范围确实有限,有些东西你customize不了,因为它没有提供那样的接口。
2、但是简单的界面编写如对动态效果没什么要求,对Desktop集成没什么要求(Java需要调用JNI来集成一些桌面特性,如WIn7任务栏图片的进度加载显示,还有比如SystemTray也只能用AWT的PopupMenu导致没法定制出和QQ、迅雷等一样的托盘效果),使用Swing还是可以的,Swing的优势也就在于跨平台性好,优于SWT。建议简单界面能使用Swing的还是不要使用SWT,对于简单界面,自己编写的L&F也搓搓有余了。
3、对于想要Charts、多媒体支持、动画效果、滤镜支持、触摸事件感应处理等富Internet绚丽界面的追求的话,建议选择用JavaFX,可插拔式用外部链接的CSS代替,一般界面的编写可以用FXML,逻辑处理用Java语言或者JavaScript。这样结构化很明显,也很现代化(参见MVC设计模式)。但是JavaFX目前Bug还是很多,很多功能不完善,比如SystemTray没有支持,Print打印功能也是在未来Java8中绑定,但是对于打印表格table似乎还没有支持(我不大确定,因为我只是初步的看了一下,还没有深入研究)。但其UI组件未来会逐渐增多。
4、目前的话Java界面编写还是JavaFX比较有前途,但是就目前的JavaFX而言似乎没有什么明显的竞争力,只能期待以后的发展了。
5、建议还是用目前主流的软件编写工具(例如论坛同志所说的“要做Desktop GUI 推荐QT C++,ui tool 和 qml 非常易用强大。”)。想要在Windows下使用的话,还是尽量调用本地化的windows API。
6、用数据库相结合的小软件编写,Java还是不错的。内置的JavaDB就不错,MySQL以及Microsoft Database也有很多开发案例,使用Oracle大型数据库就更不用说了。

Swing给我印象最深的就是绘图机制十分强大,至少在引入Android的NinePatch技术上领先JavaFX(如果有同志知道如何在JavaFX上使用类似于Android的NinePatch技术的,非常感谢告知我),一定要深刻理解java界面的绘图机制。像背景图片什么绘制是很简单的,至于图像的缩放,运用ImageOP写个缩放的,或者模糊效果等等,在Java 界面代码中用paintComponent()方法来定制背景图片的可以根据addComponentListener()中的componentResize()来缩放就可以了(使用repaint())。绘制Border或者Button的背景,图片最好使用九宫格技术,防止图片拉伸失真。在Synth中,它自带把图片分为9块的技术,使用起来十分方便,然而不如Android的NinePatch技术,因为她不仅可以分图片为9块,而且可以根据需要分为若干块我非常欣赏。最近正在写一套的基于Nimbus的lnf(当然使用了Android的NinePatch技术),感觉还不错,推荐诸位试一下,我顺带研究JavaFX,觉得前途还是有的,因为Oracle计划不断随着Java8,9,10的推出更新、支持JavaFX。
soar_angel 2013-08-20
  • 打赏
  • 举报
回复
顶楼主,我也想学习
fearlessMore 2013-08-20
  • 打赏
  • 举报
回复
引用 7 楼 valenon 的回复:
引用 6 楼 Gaowen_HAN 的回复:
引用 5 楼 u011626555 的回复:
楼主好牛!狂顶。。。。。向楼主学习
我只是计算机业余爱好者本行做营销的,对编程方面的知识涉及面很窄,只是下班回来后查了查网上资料有感而写的小程序而已。具体开发大项目还从来没做过或者精通java也谈不上。
业余爱好能发展到这水平很厉害了。
哦,反正就是平时喜欢,几年来一直利用休息时间看看CSDN论坛,自己编程写写自己想要实现的东西,然后就是什么想学一点。。发现国外的很多网站做得很好,受益不少。
valenon 2013-08-20
  • 打赏
  • 举报
回复
引用 6 楼 Gaowen_HAN 的回复:
引用 5 楼 u011626555 的回复:
楼主好牛!狂顶。。。。。向楼主学习
我只是计算机业余爱好者本行做营销的,对编程方面的知识涉及面很窄,只是下班回来后查了查网上资料有感而写的小程序而已。具体开发大项目还从来没做过或者精通java也谈不上。
业余爱好能发展到这水平很厉害了。
姜一游ptr 2013-08-19
  • 打赏
  • 举报
回复
楼主好牛!狂顶。。。。。向楼主学习
valenon 2013-08-19
  • 打赏
  • 举报
回复
不错,视图层以策略模式组合控制层,控制层和视图层又是模型层的监听者,而视图层内部又可以以组合模式实现。
齐岳 2013-08-19
  • 打赏
  • 举报
回复
赞一个
无聊找乐 2013-08-19
  • 打赏
  • 举报
回复
写的不错,顶~

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧