Lektion 2: Die Anzeige einer Namensliste
Der Umbau der Oberfläche
Wir erweitern die Oberfläche um eine Table View . Der Umbau der Oberfläche sollte mit dem SceneBuilder erfolgen. Das Ergebnis sieht bei mir so aus.
Diese Applikation wollen wir nun langsam mit Leben füllen. Die FXML-Datei, die das obige Bild erzeugt hat folgenden Inhalt.
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <BorderPane prefHeight="400.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.erichweigand.gewicht.controller.GewichtsViewController"> <top> <MenuBar BorderPane.alignment="CENTER"> <menus> <Menu mnemonicParsing="false" text="File"> <items> <MenuItem mnemonicParsing="false" onAction="#exitApplication" text="Exit" /> </items> </Menu> </menus> </MenuBar> </top> <center> <TableView fx:id="gewichtsTable" prefHeight="400.0" prefWidth="300.0" BorderPane.alignment="CENTER"> <columns> <TableColumn fx:id="datumColumn" prefWidth="150.0" text="Datum" /> <TableColumn fx:id="gewichtColumn" prefWidth="150.0" text="Gewicht" /> </columns> </TableView> </center> </BorderPane>
Anbindung an eine Datenbank
Datenbank erstellen
Erzeugen Sie in einer MySQL-Datenbank zu der Sie Zugriff haben eine neue Datenbank und erzeugen Sie darin eine Tabelle mit etwas Inhalt, die wir für die nachfolgende Lektion verwenden können. Der Befehl erstellt eine Tabelle mit 3 Spalten. Eine Spalte enthält den Primary Key, die zweite einen Datumswert und die dritte einen Zahlenwert. Es gibt viele Möglichkeiten Datums- und Zahlenwerte in einer MySQL-Datenbank zu speichern. Genaueres findet sich in der Dokumentation zu MySQL.
CREATE TABLE `gewicht`.`gewicht` ( `id` INT(10) NOT NULL AUTO_INCREMENT, `datum` DATETIME NULL, `gewicht` DOUBLE NULL, PRIMARY KEY (`id`)); INSERT INTO `gewicht`.`gewicht` (`datum`, `gewicht`) VALUES ('2017-01-01', '75.4'); INSERT INTO `gewicht`.`gewicht` (`datum`, `gewicht`) VALUES ('2017-01-02', '75.0');
Stellen Sie sicher, dass Ihr NetBeans dafür bereit ist, mit MySQL Datenbanken zu arbeiten. Eine Beschreibung wie Sie dies konfigurieren können finden Sie auf der Seite Connecting to a MySQL Database
Datenbank-Verbindung in NetBeans erstellen
- Klicken Sie oberalb der Projetkübersicht auf den Reiter Dienste
- Klicken Sie auf Datenbanken
- Rechte Maustaste Neue Verbindung …
- Treiber: MySQL (Connector/J driver) -> Weiter
- Tragen Sie hier die Verbindungsdaten zu Ihrer Datenbank ein, setzen Sie den Haken Passwort speichern und testen Sie die Verbindung mit Verbindung testen -> Weiter -> Weiter
- Verbindungsname: Gewicht
Verbindung in das Projekt einbauen
- Gehen Sie zurück auf den Reiter Projekte
- Klicken Sie auf das Package de.erichweigand.gewicht.model
- Rechtsklick Neu -> Begriffsklassen von Datenbanken
- Wählen Sie bei Datenbankverbindung die Verbindung Gewicht
- Verschieben Sie die Tabelle gewicht in das Feld Gewählte Tabellen
- Lassen Sie die Einstellungen in den weiteren Dialogen unverändert und klicken Sie auf Fertigstellen
- Klicken Sie auf den Ordner Bibliotheken
- Rechtsklick Bibliothek hinzufügen
- Fügen Sie die Bibliothek MySQL JDBC Driver hinzu
- Klicken Sie auf den Ordner Bibliotheken
- Rechtsklick Eigenschaften
- Wählen Sie bei Kategorie Bibliotheken und als Karteireiter Prozessor
- Entfernen Sie den Prozessor EclipseLink-ModelGen (JPA 2.1) und klicken auf OK
NetBeans hat nun die Voraussetzungen geschaffen, dass wir die Tabelle gewicht in unserer Datenbank in unserem Java-Programm benutzen können.
- Eine XML-Datei im Paket META-INF, die die eigentliche Datenbank-Anbindung verwaltet.
- Eine Java-Klasse Friend im Paket de.erichweigand.gewicht.model, mit der eine Zeile der Datenbank-Tabelle als Java-Objekt verwaltet werden kann.
Daten aus der Datenbank auslesen
Es fehlen noch 2 Schritte, um die Liste der Namen in der Tabellenansicht der Oberfläche darzustellen.
- Die Konfiguration der Tabelle, damit Sie weis, wie die Daten, die ihr übergeben werden dargestellt werden sollen.
- Das Auslesen der Daten und deren Übergabe an die Tabelle,
Tabellenansicht vorbereiten
Im GewichtsViewController müssen zuerst Variablen definiert werden, die den Controller mit der FXML-Datei verbinden.
@FXML TableView gewichtsTable; @FXML private TableColumn gewichtColumn; @FXML private TableColumn datumColumn;
Danach wird der gewichtColumn und der datumColumn erklärt, dass ihr im Laufe des Programms Objekte übergeben werden. In Java-Code sieht dies so aus
gewichtColumn.setCellValueFactory(new PropertyValueFactory("gewicht")); datumColumn.setCellValueFactory(new PropertyValueFactory("datum"));
Daten aus der Datenbank lesen und der Tabellenansicht übergeben
Zuerst muss die Verbindung zur Datenbank hergestellt werden. Hierfür wird die Konfiguration eingelesen, die NetBeans vorhin erstellt hat.
final EntityManagerFactory emf = Persistence.createEntityManagerFactory("GewichtPU"); final EntityManager em = emf.createEntityManager();
Dann kann die Tabelle ausgelesen werden und einer Java-Liste übergeben werden, die dann von der Tabelle dargestellt wird. Der komplette GewichtsViewController sieht dann so aus.
package de.erichweigand.gewicht.controller; import java.net.URL; import java.util.List; import java.util.ResourceBundle; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import de.erichweigand.gewicht.model.Gewicht; public class GewichtsViewController implements Initializable { final EntityManagerFactory emf = Persistence.createEntityManagerFactory("GewichtPU"); final EntityManager em = emf.createEntityManager(); private ObservableList<Gewicht> gewichtsListe; @FXML private TableView gewichtsTable; @FXML private TableColumn gewichtColumn; @FXML private TableColumn datumColumn; @Override public void initialize(URL url, ResourceBundle rb) { gewichtColumn.setCellValueFactory(new PropertyValueFactory("gewicht")); datumColumn.setCellValueFactory(new PropertyValueFactory("datum")); Query query = em.createNamedQuery("Gewicht.findAll"); List results = query.getResultList(); gewichtsListe = FXCollections.observableArrayList(results); gewichtsTable.setItems(gewichtsListe); } @FXML private void exitApplication(ActionEvent event) { System.exit(0); } }
Wenn ich das Ergebnis kompiliere und starte, sieht das Ergebnis so aus:
Die Zeitangabe sieht nicht schön aus. Um Zeitangaben im meinen Programm einheitlich zu gestalten, schreibe ich einen DateService, der in Zukunft alle Datums-spezifischen Dinge für mich erledigen wird. Der Service sieht folgendermaßen aus:
package de.erichweigand.gewicht.service; import java.text.SimpleDateFormat; import java.util.Date; public class DateService { public static String getDateString(Date date) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy"); return simpleDateFormat.format(date); } }
Danach muss noch die Definition der Datumszeile im Controller geändert werden
datumColumn.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Gewicht, Date>, ObservableValue<Date>>() { @Override public ObservableValue<Date> call(TableColumn.CellDataFeatures<Gewicht, Date> s) { String dateString = DateService.getDateString(s.getValue().getDatum()); return new SimpleObjectProperty(dateString); } });
Das neue Ergebnis sieht folgendermaßen aus.
Der komplette Code am Ende der Lektion 2 ist im Anhang der Seite zu finden.