Javafx 2 Tutorial
Javafx 2 Tutorial
ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
Objetivo
El objetivo de este tutorial es aprender cómo crear interfaces gráficas de usuario
con JavaFX 2 yConstructor de escena . Vamos a cubrir muchas características
de JavaFX 2 mediante la creación de una aplicación de direcciones y
mejorándola de forma paso a paso.
Temas en la Parte I
Conocer JavaFX 2
Creación e inicio de un proyecto JavaFX
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
9. Añadir los tres botones en la parte inferior. Tipp: Seleccione todos ellos, haga
clic derecho y llameWrap sesión | HBox . Esto, junto los agrupa. Es posible que
tenga que especificar un espaciado dentro de la caja horizontal.
10.Ahora usted debería ver algo como lo siguiente. Por favor, pruébelo usando el
menú Vista previa.
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
5. Ahora, tenemos que crear el Java principal que inicia nuestra aplicación con
el RootLayout.fxml y agrega el PersonOverview.fxml en el centro.
6. Haga clic en el paquete del controlador, New | Other ... y seleccione JavaFX
clase principal . Lo llamaremos MainApp .
Es como una obra de teatro: El Stage es el contenedor principal, que suele ser una
ventana con un borde y el típico minimizar, maximizar y cerrar botones. Dentro
de la etapa de agregar una escena que puede, por supuesto, se cambió por otra
escena. Dentro de la escena se añaden los nodos reales JavaFX como
AnchorPane, TextBox, etc.
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("AddressApp");
try {
// Load the root layout from the fxml file
FXMLLoader loader = new
FXMLLoader(MainApp.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
// Exception gets thrown if the fxml file could not be loaded
e.printStackTrace();
}
showPersonOverview();
}
/**
* Returns the main stage.
* @return
*/
public Stage getPrimaryStage() {
return primaryStage;
}
/**
* Shows the person overview scene.
*/
public void showPersonOverview() {
try {
// Load the fxml file and set into the center of the main
layout
FXMLLoader loader = new
FXMLLoader(MainApp.class.getResource("view/PersonOverview.fxml"));
AnchorPane overviewPage = (AnchorPane) loader.load();
rootLayout.setCenter(overviewPage);
} catch (IOException e) {
// Exception gets thrown if the fxml file could not be loaded
e.printStackTrace();
}
}
Trate de entender el código. Los diversos comentarios deben darle algunas pistas
sobre lo que está pasando.
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
import java.util.Calendar;
/**
* Model class for a Person.
*
* @author Marco Jakob
*/
public class Person {
/**
* Default constructor.
*/
public Person() {
}
/**
* Constructor with some initial data.
*
* @param firstName
* @param lastName
*/
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.postalCode = 1234;
this.city = "some city";
this.birthday = Calendar.getInstance();
}
Estamos trabajando con clases de vista JavaFX que siempre necesitan ser
informados de los cambios realizados en la lista de personas. Esto es
importante, ya que de lo contrario la vista no estaría en sintonía con los
datos. Para este propósito, JavaFX introduce algunas nuevas clases de
colección .
A partir de esas colecciones, necesitamos la ObservableList . Para crear
un nuevo ObservableList , agregue el código siguiente al principio
del MainApp clase. También vamos a añadir un constructor que crea
algunos datos de ejemplo y un método getter público:
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
// ...
/**
* The data as an observable list of Persons.
*/
private ObservableList<Person> personData =
FXCollections.observableArrayList();
/**
* Constructor
*/
public MainApp() {
// Add some sample data
personData.add(new Person("Hans", "Muster"));
personData.add(new Person("Ruth", "Mueller"));
personData.add(new Person("Heinz", "Kurz"));
personData.add(new Person("Cornelia", "Meier"));
personData.add(new Person("Werner", "Meyer"));
personData.add(new Person("Lydia", "Kunz"));
personData.add(new Person("Anna", "Best"));
personData.add(new Person("Stefan", "Meier"));
personData.add(new Person("Martin", "Mueller"));
}
/**
* Returns the data as an observable list of Persons.
* @return
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
*/
public ObservableList<Person> getPersonData() {
return personData;
}
El PersonOverviewController
Ahora vamos a ver finalmente algunos datos en nuestra mesa.
PersonOverviewController.java
1 public class PersonOverviewController {
2 @FXML
3 private TableView<Person> personTable;
4 @FXML
5 private TableColumn<Person, String> firstNameColumn;
6 @FXML
7 private TableColumn<Person, String> lastNameColumn;
8
9 @FXML
10 private Label firstNameLabel;
11 @FXML
12 private Label lastNameLabel;
13 @FXML
14 private Label streetLabel;
15 @FXML
16 private Label postalCodeLabel;
17 @FXML
18 private Label cityLabel;
19 @FXML
20 private Label birthdayLabel;
21
22 // Reference to the main application
23 private MainApp mainApp;
24
25 /**
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
26 * The constructor.
27 * The constructor is called before the initialize() method.
28 */
29 public PersonOverviewController() {
30 }
31
32 /**
33 * Initializes the controller class. This method is automatically
34 called
35 * after the fxml file has been loaded.
36 */
37 @FXML
38 private void initialize() {
39 // Initialize the person table
40 firstNameColumn.setCellValueFactory(new
41 PropertyValueFactory<Person, String>("firstName"));
42 lastNameColumn.setCellValueFactory(new
43 PropertyValueFactory<Person, String>("lastName"));
44 }
45
46 /**
47 * Is called by the main application to give a reference back to
48 itself.
49 *
50 * @param mainApp
51 */
52 public void setMainApp(MainApp mainApp) {
53 this.mainApp = mainApp;
54
// Add observable list data to the table
personTable.setItems(mainApp.getPersonData());
}
}
Todos los campos y métodos donde el archivo fxml necesidades de acceso deben
ser anotados con @ FXML . En realidad, sólo si son privados, pero es mejor
tenerlos privado y marcarlos con la anotación!.
El initialize () método se llama de forma automática después de que se haya
cargado el archivo fxml. En este momento, todos los campos FXML deberían
haberse inicializado ya.
El PropertyValueFactory que establecimos en las columnas de mesa se utilizan
para determinar qué campo dentro de la persona objeto se debe utilizar para la
columna en particular.
El setMainApp (...) método debe ser llamado por el MainApp clase. Esto nos
da una manera de acceder a la MainApp objeto y obtener la lista de datos y otras
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
¡Enhorabuena!
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
49 }
50
51 /**
52 * Checks the String whether it is a valid date.
53 *
54 * @param dateString
55 * @return true if the String is a valid date
56 */
57 public static boolean validString(String dateString) {
58 try {
59 DATE_FORMAT.parse(dateString);
60 return true;
61 } catch (ParseException e) {
62 return false;
63 }
}
}
12 // clear person
13 showPersonDetails(null);
14
15 // Listen for selection changes
16
17 personTable.getSelectionModel().selectedItemProperty().addListener(new
18 ChangeListener<Person>() {
19
20 @Override
21 public void changed(ObservableValue<? extends Person> observable,
Person oldValue, Person newValue) {
showPersonDetails(newValue);
}
});
}
/**
1
* Called when the user clicks on the delete button.
2
*/
3
@FXML
4
private void handleDeletePerson() {
5
int selectedIndex =
6
personTable.getSelectionModel().getSelectedIndex();
7
personTable.getItems().remove(selectedIndex);
8
}
Control de errores
3. Crear el controlador PersonEditDialogController :
4. PersonEditDialogController.java) download
1 package ch.makery.address;
2
3 import javafx.fxml.FXML;
4 import javafx.scene.control.Dialogs;
5 import javafx.scene.control.TextField;
6 import javafx.stage.Stage;
7 import ch.makery.address.model.Person;
8 import ch.makery.address.util.CalendarUtil;
9
10 /**
11 * Dialog to edit details of a person.
12 *
13 * @author Marco Jakob
14 */
15 public class PersonEditDialogController {
16
17 @FXML
18 private TextField firstNameField;
19 @FXML
20 private TextField lastNameField;
21 @FXML
22 private TextField streetField;
23 @FXML
24 private TextField postalCodeField;
25 @FXML
26 private TextField cityField;
27 @FXML
28 private TextField birthdayField;
29
30
31 private Stage dialogStage;
32 private Person person;
33 private boolean okClicked = false;
34
35 /**
36 * Initializes the controller class. This method is automatically
37 called
38 * after the fxml file has been loaded.
39 */
40 @FXML
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
98 }
99
100 /**
101 * Called when the user clicks cancel.
102 */
103 @FXML
104 private void handleCancel() {
105 dialogStage.close();
106 }
107
108 /**
109 * Validates the user input in the text fields.
110 *
111 * @return true if the input is valid
112 */
113 private boolean isInputValid() {
114 String errorMessage = "";
115
116 if (firstNameField.getText() == null ||
117 firstNameField.getText().length() == 0) {
118 errorMessage += "No valid first name!\n";
119 }
120 if (lastNameField.getText() == null ||
121 lastNameField.getText().length() == 0) {
122 errorMessage += "No valid last name!\n";
123 }
124 if (streetField.getText() == null ||
125 streetField.getText().length() == 0) {
126 errorMessage += "No valid street!\n";
127 }
128
129 if (postalCodeField.getText() == null ||
130 postalCodeField.getText().length() == 0) {
131 errorMessage += "No valid postal code!\n";
132 } else {
133 // try to parse the postal code into an int
134 try {
135 Integer.parseInt(postalCodeField.getText());
136 } catch (NumberFormatException e) {
137 errorMessage += "No valid postal code (must be an
138 integer)!\n";
139 }
140 }
141
142 if (cityField.getText() == null || cityField.getText().length()
143 == 0) {
144 errorMessage += "No valid city!\n";
145 }
146
147 if (birthdayField.getText() == null ||
148 birthdayField.getText().length() == 0) {
149 errorMessage += "No valid birthday!\n";
150 } else {
151 if (!CalendarUtil.validString(birthdayField.getText())) {
152 errorMessage += "No valid birthday. Use the format yyyy-
153 mm-dd!\n";
}
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
if (errorMessage.length() == 0) {
return true;
} else {
// Show the error message
Dialogs.showErrorDialog(dialogStage, errorMessage,
"Please correct invalid fields", "Invalid Fields");
return false;
}
}
}
17 dialogStage.initModality(Modality.WINDOW_MODAL);
18 dialogStage.initOwner(primaryStage);
19 Scene scene = new Scene(page);
20 dialogStage.setScene(scene);
21
22 // Set the person into the controller
23 PersonEditDialogController controller = loader.getController();
24 controller.setDialogStage(dialogStage);
25 controller.setPerson(person);
26
27 // Show the dialog and wait until the user closes it
28 dialogStage.showAndWait();
29
30 return controller.isOkClicked();
31
32 } catch (IOException e) {
33 // Exception gets thrown if the fxml file could not be loaded
34 e.printStackTrace();
35 return false;
36 }
}
Agregue los siguientes métodos para la PersonOverviewController :
PersonOverviewController.java
1 /**
2 * Called when the user clicks the new button.
3 * Opens a dialog to edit details for a new person.
4 */
5 @FXML
6 private void handleNewPerson() {
7 Person tempPerson = new Person();
8 boolean okClicked = mainApp.showPersonEditDialog(tempPerson);
9 if (okClicked) {
10 mainApp.getPersonData().add(tempPerson);
11 }
12 }
13
14 /**
15 * Called when the user clicks the edit button.
16 * Opens a dialog to edit details for the selected person.
17 */
18 @FXML
19 private void handleEditPerson() {
20 Person selectedPerson =
21 personTable.getSelectionModel().getSelectedItem();
22 if (selectedPerson != null) {
23 boolean okClicked = mainApp.showPersonEditDialog(selectedPerson);
24 if (okClicked) {
25 refreshPersonTable();
26 showPersonDetails(selectedPerson);
27 }
28
29 } else {
30 // Nothing selected
31 Dialogs.showWarningDialog(mainApp.getPrimaryStage(),
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
26 DE NOVIEMBRE TH , 2012
4
5 .label {
6 -fx-font-size: 11pt;
7 -fx-font-family: "Segoe UI Semibold";
8 -fx-text-fill: white;
9 -fx-opacity: 0.6;
10 }
11
12 .label-bright {
13 -fx-font-size: 11pt;
14 -fx-font-family: "Segoe UI Semibold";
15 -fx-text-fill: white;
16 -fx-opacity: 1;
17 }
18
19 .label-header {
20 -fx-font-size: 32pt;
21 -fx-font-family: "Segoe UI Light";
22 -fx-text-fill: white;
23 -fx-opacity: 1;
24 }
25
26 .table-view {
27 -fx-base: #1d1d1d;
28 -fx-control-inner-background: #1d1d1d;
29 -fx-background-color: #1d1d1d;
30 -fx-table-cell-border-color: transparent;
31 -fx-table-header-border-color: transparent;
32 -fx-padding: 5;
33 }
34
35 .table-view .column-header-background {
36 -fx-background-color: transparent;
37 }
38
39 .table-view .column-header, .table-view .filler {
40 -fx-size: 35;
41 -fx-border-width: 0 0 1 0;
42 -fx-border-color:
43 transparent
44 transparent
45 derive(-fx-base, 80%)
46 transparent;
47 -fx-border-insets: 0 10 1 0;
48 }
49
50 .table-view .column-header .label {
51 -fx-font-size: 20pt;
52 -fx-font-family: "Segoe UI Light";
53 -fx-text-fill: white;
54 -fx-alignment: center-left;
55 -fx-opacity: 1;
56 }
57
58 .table-view:focused .table-row-cell:filled:focused:selected {
59 -fx-background-color: -fx-focus-color;
60 }
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
61
62 .split-pane:horizontal > * > .split-pane-divider {
63 -fx-border-color: transparent #1d1d1d transparent #1d1d1d;
64 -fx-background-color: transparent, derive(#1d1d1d,20%);
65 }
66
67 .split-pane {
68 -fx-padding: 1 0 0 0;
69 }
70
71 .menu-bar {
72 -fx-background-color: derive(#1d1d1d,20%);
73 -fx-selection-bar: derive(-fx-background,-7%);
74 }
75
76 .menu-bar .label {
77 -fx-font-size: 14pt;
78 -fx-font-family: "Segoe UI Light";
79 -fx-text-fill: white;
80 -fx-opacity: 0.9;
81 }
82
83 .text-field {
84 -fx-font-size: 12pt;
85 -fx-font-family: "Segoe UI Semibold";
86 }
87
88
89
90 /*
91 * Metro style Push Button
92 * Author: Pedro Duque Vieira
93 * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-
94 controls-on-java/
95 */
96 .button {
97 -fx-padding: 5 22 5 22;
98 -fx-border-color: #e2e2e2;
99 -fx-border-width: 2;
100 -fx-background-radius: 0;
101 -fx-background-color: #1d1d1d;
102 -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
103 -fx-font-size: 11pt;
104 -fx-text-fill: #d8d8d8;
105 -fx-background-insets: 0 0 0 0, 0, 1, 2;
106 }
107
108 .button:hover {
109 -fx-background-color: #3a3a3a;
110 }
111
112 .button:pressed, .button:default:hover:pressed {
113 -fx-background-color: white;
114 -fx-text-fill: #1d1d1d;
115 }
116
117 .button:focused {
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
Ahora tenemos que conectar el CSS a nuestra escena. Podemos hacer esto
mediante programación en el código Java, pero vamos a utilizar el
Generador de Escena para añadirlo a nuestros ficheros fxml:
Usted ya debe ver algunos cambios ahora: La tabla y los botones son de
color negro. Si selecciona un botón y mira la parte CSS en la vista
Propiedades, verá que ya hay una clase de estilo por defecto
llamada botón .
El archivo de icono
MainApp.java
public void start(Stage primaryStage) {
1 this.primaryStage = primaryStage;
2 this.primaryStage.setTitle("AddressApp");
3 // Set the application icon
4 this.primaryStage.getIcons().add(new
5 Image("file:resources/images/address_book_32.png"));
6
7 try {
8 // Load the root layout from the fxml file
9 FXMLLoader loader = new
10 FXMLLoader(MainApp.class.getResource("view/RootLayout.fxml"));
11 rootLayout = (BorderPane) loader.load();
12 Scene scene = new Scene(rootLayout);
13 primaryStage.setScene(scene);
14 primaryStage.show();
15 } catch (IOException e) {
16 // Exception gets thrown if the fxml file could not be loaded
17 e.printStackTrace();
18 }
19
20 showPersonOverview();
}
También puede añadir un icono a la etapa del diálogo de edición persona,
por supuesto.
MainApp.java
1 /**
2 * Returns the person file preference, i.e. the file that was last
3 opened.
4 * The preference is read from the OS specific registry. If no such
5 * preference can be found, null is returned.
6 *
7 * @return
8 */
9 public File getPersonFilePath() {
10 Preferences prefs = Preferences.userNodeForPackage(MainApp.class);
11 String filePath = prefs.get("filePath", null);
12 if (filePath != null) {
13 return new File(filePath);
14 } else {
15 return null;
16 }
17 }
18
19 /**
20 * Sets the file path of the currently loaded file.
21 * The path is persisted in the OS specific registry.
22 *
23 * @param file the file or null to remove the path
24 */
25 public void setPersonFilePath(File file) {
26 Preferences prefs = Preferences.userNodeForPackage(MainApp.class);
27 if (file != null) {
28 prefs.put("filePath", file.getPath());
29
30 // Update the stage title
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
Una de las maneras más comunes para conservar los datos es el uso de
una base de datos. Las bases de datos suelen contener algún tipo de datos
relacionales (como tablas), mientras que los datos que necesitamos para
salvar son objetos. Esto se conoce como la diferencia de impedancia objeto-
relacional . Es un poco de trabajo para que coincida con los objetos a las
tablas de bases de datos relacionales. Hay algunos de los marcos que
ayudan con el juego (por ejemplo, Hibernate , el más popular), pero todavía
requiere un poco de trabajo de configurar.
En nuestro modelo de datos simple es mucho más fácil de usar
XML. Vamos a utilizar una biblioteca llamada XStream . Con sólo unas
pocas líneas de código que esto nos permitirá generar XML de salida
como esta:
sample.xml
1 <list>
2 <person>
3 <firstName>Hans</firstName>
4 <lastName>Muster</lastName>
5 <street>some street</street>
6 <postalCode>1234</postalCode>
7 <city>some city</city>
8 <birthday>
9 <time>1354035227734</time>
10 <timezone>Europe/Berlin</timezone>
11 </birthday>
12 </person>
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
13 <person>
14 <firstName>Anna</firstName>
15 <lastName>Best</lastName>
16 <street>some street</street>
17 <postalCode>1234</postalCode>
18 <city>some city</city>
19 <birthday>
20 <time>1354035227734</time>
21 <timezone>Europe/Berlin</timezone>
22 </birthday>
23 </person>
24 </list>
26 */
27 public static String readFile(File file) throws IOException {
28 StringBuffer stringBuffer = new StringBuffer();
29
30 BufferedReader reader = Files.newBufferedReader(file.toPath(),
31 CHARSET);
32
33 String line = null;
34 while ((line = reader.readLine()) != null) {
35 stringBuffer.append(line);
36 }
37
38 reader.close();
39
40 return stringBuffer.toString();
41 }
42
43 /**
44 * Saves the content String to the specified file.
45 *
46 * @param content
47 * @param file
48 * @throws IOException thrown if an I/O error occurs opening or
49 creating the file
50 */
51 public static void saveFile(String content, File file) throws
52 IOException {
53 BufferedWriter writer = Files.newBufferedWriter(file.toPath(),
54 CHARSET);
writer.write(content, 0, content.length());
writer.close();
}
}
Usando XStream
MainApp.java
/**
1 * Loads person data from the specified file. The current person data
2 will
3 * be replaced.
4 *
5 * @param file
6 */
7 @SuppressWarnings("unchecked")
8 public void loadPersonDataFromFile(File file) {
9 XStream xstream = new XStream();
10 xstream.alias("person", Person.class);
11
12 try {
13 String xml = FileUtil.readFile(file);
14
15 ArrayList<Person> personList = (ArrayList<Person>)
16 xstream.fromXML(xml);
17
18 personData.clear();
19 personData.addAll(personList);
20
21 setPersonFilePath(file);
22 } catch (Exception e) { // catches ANY exception
23 Dialogs.showErrorDialog(primaryStage,
24 "Could not load data from file:\n" + file.getPath(),
25 "Could not load data", "Error", e);
26 }
27 }
28
29 /**
30 * Saves the current person data to the specified file.
31 *
32 * @param file
33 */
34 public void savePersonDataToFile(File file) {
35 XStream xstream = new XStream();
36 xstream.alias("person", Person.class);
37
38 // Convert ObservableList to a normal ArrayList
39 ArrayList<Person> personList = new ArrayList<>(personData);
40
41 String xml = xstream.toXML(personList);
42 try {
43 FileUtil.saveFile(xml, file);
44
45 setPersonFilePath(file);
46 } catch (Exception e) { // catches ANY exception
47 Dialogs.showErrorDialog(primaryStage,
48 "Could not save data to file:\n" + file.getPath(),
49 "Could not save data", "Error", e);
50 }
}
Para el manejo de las acciones del menú que necesitaremos una nueva
clase de controlador. Crear una clase RootLayoutController dentro del
paquete controlador ch.makery.address .
Añadir el contenido siguiente al controlador:
(RootLayoutController.java) download
1 package ch.makery.address;
2
3 import java.io.File;
4
5 import javafx.fxml.FXML;
6 import javafx.scene.control.Dialogs;
7 import javafx.stage.FileChooser;
8
9 /**
10 * The controller for the root layout. The root layout provides the
11 basic
12 * application layout containing a menu bar and space where other
13 JavaFX
14 * elements can be placed.
15 *
16 * @author Marco Jakob
17 */
18 public class RootLayoutController {
19
20 // Reference to the main application
21 private MainApp mainApp;
22
23 /**
24 * Is called by the main application to give a reference back to
25 itself.
26 *
27 * @param mainApp
28 */
29 public void setMainApp(MainApp mainApp) {
30 this.mainApp = mainApp;
31 }
32
33 /**
34 * Creates an empty address book.
35 */
36 @FXML
37 private void handleNew() {
38 mainApp.getPersonData().clear();
39 mainApp.setPersonFilePath(null);
40 }
41
42 /**
43 * Opens a FileChooser to let the user select an address book to
44 load.
45 */
46 @FXML
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
104
105 /**
106 * Opens an about dialog.
107 */
108 @FXML
109 private void handleAbout() {
110 Dialogs.showInformationDialog(mainApp.getPrimaryStage(),
111 "Author: Marco Jakob\nWebsite: http://edu.makery.ch", "AddressApp",
112 "About");
113 }
/**
* Closes the application.
*/
@FXML
private void handleExit() {
System.exit(0);
}
3. Cerrar Escena Builder y golpe Refresh (F5) en la carpeta raíz del proyecto. Esto
hará que Eclipse conscientes de los cambios que ha realizado en el Generador de
escena.
Conexión del MainApp y RootLayoutController
15
16 // Give the controller access to the main app
17 RootLayoutController controller = loader.getController();
18 controller.setMainApp(this);
19
20 primaryStage.show();
21 } catch (IOException e) {
22 // Exception gets thrown if the fxml file could not be loaded
23 e.printStackTrace();
24 }
25
26 showPersonOverview();
27
28 // Try to load last opened person file
29 File file = getPersonFilePath();
30 if (file != null) {
31 loadPersonDataFromFile(file);
}
}
Observe los dos cambios: Las líneas que dan acceso al controlador de la
aplicación principal y las tres últimas líneas para cargar el último archivo
abierto persona .
¿Cómo funciona?
Hacer una prueba de manejo de su solicitud, usted debe ser capaz de
utilizar los menús para guardar los datos de la persona a un archivo y
cargarlo de nuevo. Después de un reinicio, debe cargar automáticamente
el último archivo utilizado.
Vamos a utilizar un gráfico de barras que contiene una barra para cada
mes. Cada barra muestra cuántas personas tienen su cumpleaños en ese mes
particular.
Las estadísticas FXML View
1. Empezamos creando un BirthdayStatistics.fxml archivo dentro de
nuestra ch.makery.address.view paquete ( Haga clic en el paquete | Nuevo |
otras ... | New FXML documento ).
2. Abra la BirthdayStatistics.fxml archivo en el Generador de escena.
3. Seleccione la raíz AnchorPane y establezca el Ancho Pref a 620 y la altura Pref a
450.
4. Añadir un BarChart al AnchorPane .
5. Haga clic en el BarChart y seleccione Ajustar a los padres .
6. Guarde el archivo fxml, vaya a Eclipse y actualizar el proyecto.
Antes de que nos volveremos a Constructor de escena, lo primero que va a crear
el controlador y el alambre todo para arriba en nuestro MainApp.
El controlador de Estadísticas
En el paquete del controlador ch.makery.address crear una clase Java
llamada BirthdayStatisticsController.java .
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/
Vamos a utilizar un gráfico de barras que contiene una barra para cada
mes. Cada barra muestra cuántas personas tienen su cumpleaños en ese mes
particular.
Las estadísticas FXML View
1. Empezamos creando un BirthdayStatistics.fxml archivo dentro de
nuestra ch.makery.address.view paquete ( Haga clic en el paquete | Nuevo |
otras ... | New FXML documento ).
2. Abra la BirthdayStatistics.fxml archivo en el Generador de escena.
3. Seleccione la raíz AnchorPane y establezca el Ancho Pref a 620 y la altura Pref a
450.
4. Añadir un BarChart al AnchorPane .
5. Haga clic en el BarChart y seleccione Ajustar a los padres .
6. Guarde el archivo fxml, vaya a Eclipse y actualizar el proyecto.
Antes de que nos volveremos a Constructor de escena, lo primero que va a crear
el controlador y el alambre todo para arriba en nuestro MainApp.
El controlador de Estadísticas
En el paquete del controlador ch.makery.address crear una clase Java
llamada BirthdayStatisticsController.java .
Primero echemos un vistazo a toda la clase del controlador antes de empezar a
explicar:
http://edu.makery.ch/blog/2012/11/16/javafx-tutorial-addressapp-1/