Programmieren > Sprachen > Java > Schulung 1

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

Verbindung in das Projekt einbauen

NetBeans hat nun die Voraussetzungen geschaffen, dass wir die Tabelle gewicht in unserer Datenbank in unserem Java-Programm benutzen können.

Daten aus der Datenbank auslesen

Es fehlen noch 2 Schritte, um die Liste der Namen in der Tabellenansicht der Oberfläche darzustellen.

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.

GewichtsLektion02.tar