Graphical User Interfaces mit JavaFX Programmiermethodik Eva Zangerle Universität Innsbruck
Überblick
GUI GUI = Graphical User Interface Grafische Benutzeroberfläche Steuerung der Anwendung durch Maus- und Tastatur mit Hilfe von GUI-Komponenten (Fenster, Buttons, Slider, Scrollbar etc.) Wichtige Konzepte bei der GUI-Programmierung Komponenten Anordnung der einzelnen Komponenten Layout Anordnung der einzelnen Komponenten am Bildschirm Ereignisgesteuerte Programmierung Komponenten haben eigene Funktionalität. Komponenten reagieren auf Ereignisse (Events). Abfolge der Benutzereingaben bestimmt den Programmablauf! Programmiermethodik - GUI-Programmierung 3
GUI-Programmierung in Java Java 1.0: Abstract Windowing Toolkit Bestandteil der Java API Minimalistisch Spezifisch (OS) Low-level Programmierung Java 1.2: Swing (leichtgewichtige Komponenten) Basiert auf AWT Bestandteil der Java Foundation Classes (JFC) JFC ist eine Sammlung von Programmierschnittstellen (APIs) für die Erstellung portabler Java GUIs. Plattformunabhängig Bessere Performance Programmiermethodik - GUI-Programmierung 4
Java Swing Viele Komponenten Leichtgewichtig (direkt von Java gerendert (gezeichnet)) Auf allen Plattformen sehen die Komponenten gleich aus. Look-and-Feel (Erscheinungsbild) konfigurierbar Windows, Motif, Metal, Nimbus Einige Komponenten zusätzlich zu AWT Drag and Drop Tooltips Automatisches Double Buffering (zuerst zeichnen, dann anzeigen) Code der Bibliotheksklassen ruft den Programmcode des Anwendungsprogrammierers auf, wenn das entsprechende Grafikelement bei der Programmausführung benutzt wird (z.b. Mausklick). Programmiermethodik - GUI-Programmierung 5
Java Swing-Komponenten JButton JCheckBox JComboBox JList JSlider JSpinner JRadioButton JTextField JPasswordField JMenu JProgressBar JSeparator JLabel JToolTip Programmiermethodik - GUI-Programmierung 6
JavaFX Ursprünglich eigenständig entwickelt Skriptsprache JavaFX-Script für Animationen gedacht API (Application Programmer Interface) für die Erstellung von GUIs Seit Java 1.7 und JavaFX 2.2 mitgeliefertes Graphics-Toolkit Seit Java 1.8 Versionsnummer angepasst (JavaFX 8) Langfristig als Ersatz für Swing geplant Läuft Standalone und im Browser Multimedia-Inhalte CSS (Cascading Style Sheet) Ermöglicht RIA Rich Internet Applications Programmiermethodik - GUI-Programmierung 7
JavaFX
JavaFX-Grundlagen Jede JavaFX Applikation erbt von javafx.application.application public class HelloWorldApplication extends Application Application-Klasse stellt Umgebung (Fenster, Systemmenü und Standardschaltflächen) zur Verfügung GUI ist immer baumartig aufgebaut Programmiermethodik - GUI-Programmierung 9
JavaFX-Aufbau Stage (Fenster) Scene (Container) Control (Widget) Programmiermethodik - GUI-Programmierung 10
JavaFX-Aufbau (2) Angelehnt an Theater-Aufbau: Stage: Fenster und damit Hauptcontainer (Rand, Buttons zum Minimieren, Maximieren, Schließen) Scene-Objekt: Inhaltscontainer (kann ausgetauscht werden) Pane-Objekte: Untercontainer, der die UI-Elemente (Widgets) enthält Programmiermethodik - GUI-Programmierung 11
Beispiel Fenster Widget Layout- Container Programmiermethodik - GUI-Programmierung 12
Hello World Siehe HelloWorldApplication.java start()-methode wird überschrieben beim Erzeugen der Anwendung automatisch aufgerufen legt Inhalt des Fensters fest Parameter primarystage wird von JavaFX automatisch erzeugt Stage settitle() setzt Bezeichnung des Fensters in Header show() zeigt definiertes Fenster an StackPane Container für UI-Elemente (in diesem Fall Button) wird der Scene hinzugefügt Scene Container für Inhalt des Fensters launch startet die Anwendung Programmiermethodik - GUI-Programmierung 13
JavaFX-Aufbau (3) Jede Scene ist durch einen scene graph bestimmt Scene enthält (verschachtelte) Nodes StackPane Hbox Node (abstract) Parent (abstract) Group (nonresizable) Region (resizable + CSS) Pane TabPane Vbox TilePane FlowPane AnchorPane TitledPane Control (abstract, resizable, CSS) SplitPane BorderPane GridPane Accordian ToolBar Abbildung angelehnt an https://amyfowlersblog.wordpress.com/2011/06/02/javafx2-0-layout-a-class-tour/ Programmiermethodik - GUI-Programmierung 14
Beispiel-Widgets Programmiermethodik - GUI-Programmierung 15
JavaFX-Aufbau (4) Layout kann durch Verschachtelung von Nodes definiert werden JavaFX stellt eine Vielzahl von Widgets zur Verfügung Widgets bieten Methoden, mit denen Widget manipuliert werden kann bzw. beispielsweise selektierte Werte oder eingegebene Texte abgefragt werden können Ablaufsteuerung basiert auch auf Widgets (was passiert, wenn Button gedrückt wurde) ereignisbasierte Programmierung Programmiermethodik - GUI-Programmierung 16
Layouts
Motivation Layout bestimmt die Positionierung von Elementen in der GUI Naiver Ansatz: absolute Positionierung der Elemente mittels x- und y-koordinaten btn_stop.setlayoutx(100.0); btn_stop.setlayouty(0.0); btn_start.setlayoutx(150.0); btn_start.setlayouty(0.0); btn_pause.setlayoutx(200.0); btn_pause.setlayouty(0.0); label.setlayoutx(0); label.setlayouty(0); Pane root = new Pane(); root.getchildren().add(label); Programmiermethodik - GUI-Programmierung 18
Motivation (2) Probleme: Plattformunabhängigkeit (sieht Applikation in Windows, Linux und MacOS noch gleich aus?) Fedora 20: Windows 7: Programmiermethodik - GUI-Programmierung 19
Motivation (3) Skalierung ( Aufziehen des Fensters) Internationalisierung (Elemente in verschiedenen Sprachen) Lösung: Flexible Layoutmanager von JavaFX verwenden Programmiermethodik - GUI-Programmierung 20
Layouts Flexible Anordnung der UI-Elemente in den Panes Verschiedene Panes verfügen über verschiedene Layouts (z.b. FlowPane, BorderPane, etc.) Mit Skalierung des Fensters werden auch alle UI-Elemente skaliert und neu positioniert Skalierung und Größe: Initiale Größe der Stage kann im Konstruktor übergeben werden Größe der Widgets: minimale, maximale und bevorzugte Größe (prefwidth, prefheight) können angegeben werden Diese Größen der Widgets werden vom LayoutManager abgefragt und bei Bedarf verwendet. Programmiermethodik - GUI-Programmierung 21
BorderPane Pane wird in fünf Bereiche unterteilt Pro Bereich ein Widget Top, Left, Right, Bottom-Bereiche werden in ihrer bevorzugten Größe erzeugt Bei Skalierung bleiben diese vier Elemente gleich, Center wird vergrößert/verkleinert Falls Fenster zu klein ist, kommt es zu Überlappungen Abbildung übernommen aus https://docs.oracle.com/javafx/2/layout/builtin_layouts.htm Programmiermethodik - GUI-Programmierung 22
BorderPane (2) BorderPane root = new BorderPane(); root.settop(label); BorderPane.setAlignment(label, Pos.CENTER); BorderPane.setMargin(label, new Insets(10.0, 2.0, 2.0, 2.0)); root.setleft(btn_start); root.setcenter(btn_stop); root.setright(btn_pause); Inset = Inside Offset für alle vier Seiten eines Rechteckes (in Pixel angegeben) Programmiermethodik - GUI-Programmierung 23
FlowPane Pane ordnet Widgets nacheinander an (abhängig von deren bevorzugter Größe) Horizontale FlowPane Widgets horizontal nebeneinander angeordnet (Reihe) Vertikale FlowPane Widgets vertikal untereinander angeordnet (Spalte) Programmiermethodik - GUI-Programmierung 24
FlowPane //FlowPane FlowPane root = new FlowPane(); // vertical FlowPane //FlowPane root = new FlowPane(Orientation.VERTICAL); root.setstyle("-fx-background-color: #ffffff"); root.setpadding(new Insets(5.0, 5.0, 5.0, 5.0)); root.sethgap(15.0); root.setvgap(10.0); root.getchildren().add(label); root.getchildren().add(buttonstart); root.getchildren().add(buttonstop); root.getchildren().add(buttonpause); Programmiermethodik - GUI-Programmierung 25
VBox, HBox Widgets werden in Reihe bzw. in Spalte angeordnet Reihenfolge der Widgets entspricht der Einfügereihenfolge Bei Skalierung kann angegeben werden, ob und welche Komponenten mitwachsen (grow priority). HBox root = new HBox(); root.setspacing(20.0); root.setpadding(new Insets(5.0, 5.0, 5.0, 5.0)); root.getchildren().add(label); root.getchildren().add(buttonstart); root.getchildren().add(buttonstop); root.getchildren().add(buttonpause); Programmiermethodik - GUI-Programmierung 26
GridPane Erzeugt ein Raster aus Zeilen und Spalten Widgets können in Zellen eingefügt werden Zuordnung mittels Koordinatensystem GridPane root = new GridPane(); root.setpadding(new Insets(5.0, 5.0, 5.0, 5.0)); root.sethgap(5.0); root.add(label, 0, 0); root.add(buttonstart, 1,1); root.add(buttonstop, 2,1); root.add(buttonpause, 3,1); Programmiermethodik - GUI-Programmierung 27
Weitere Layouts StackPane Stapelt Widgets übereinander AnchorPane Widgets können an vier Seiten der Pane verankert werden Bei Skalierung wird die Position relativ beibehalten TilePane Ähnliches Verhalten wie FlowPane Unterteilung in Tiles gleicher Größe (horizontal oder vertikal) Programmiermethodik - GUI-Programmierung 28
Verschachtelung Panes können beliebig verschachtelt werden Beispiel: BorderPane mit FlowPane RIGHT GridPane CENTER HBox im TOP Abbildung übernommen aus https://docs.oracle.com/javafx/2/layout/builtin_layouts.htm Programmiermethodik - GUI-Programmierung 29
Beispiel Siehe TweetInspectorApplication.java (Paket at.ac.uibk.dbis.informatik.gui.tweetinspector) TweetInspectorUI für Implementierung des User Interfaces. Programmiermethodik - GUI-Programmierung 30
Ereignisbasierte Programmierung
Ereignisbasierte Programmierung Der Kontrollfluss eines Systems wird durch Ereignisse und nicht durch Kontrollstrukturen oder Funktionsaufrufe bestimmt. Beispiele für Ereignisse Mausklick Eingabe per Tastatur etc. Selektion Drag and Drop Typische Anwendung Interaktive Systeme Interaktion zwischen Benutzer und grafischer Benutzerschnittstelle Programmierung von Sensoren Messwerte bestimmen weiteren Ablauf Programmiermethodik - GUI-Programmierung 32
Generelle Idee Zuhörer (Listener) registrieren sich für bestimmte Ereignisse. Die Quelle schickt eine Benachrichtigung wenn ein Ereignis eintritt. register Listeners Event Source notify Programmiermethodik - GUI-Programmierung 33
Event-Objekte Ein Ereignis wird durch ein Objekt repräsentiert. Es gibt unterschiedliche Ereignistypen, von denen Objekte angelegt werden können. z.b. Klick auf Button erzeugt ActionEvent Alle Ereignistypen erben von javafx.event.event. Ereignisse werden meist von Widgets erzeugt. Ein Ereignisobjekt beinhaltet Informationen über Ereignistyp (Event Type) Source (Quelle des Ereignisses (z.b. auf welchen Button wurde geklickt?)) Target Ereignis (Handler) Programmiermethodik - GUI-Programmierung 34
Event-Objekte (2) Typische Verarbeitung Endlosschleife (Event-Schleife) in der die Ereignisse generiert werden (auf Aktionen warten). Interne Verwaltung eines Puffers für die einzelnen Ereignisse. Kontrollfluss der Event-Schleife sollte unabhängig vom Kontrollfluss der Empfänger sein. Nebenläufigkeit! Abbildung übernommen aus https://docs.oracle.com/javafx/2/events/processing.htm Programmiermethodik - GUI-Programmierung 35
Listener Möchte ein Objekt von einer Komponente über bestimmtes Ereignis benachrichtigt werden, dann muss die Komponente: ein passendes Interface implementieren und sich als Listener bei der Komponente (Source) registrieren. Interface: public interface EventHandler <T extends Event> extends EventListener { void handle(t event); } Methode handle() reagiert auf auftretendes Ereignis. Diese Implementierung wird als Event Handler bezeichnet. Sehr oft als innere (anonyme) Klasse implementiert. Programmiermethodik - GUI-Programmierung 36
Event Handler Handler als Listener registrieren mittels seton<eventtyp>- Methode des zu überwachenden Widgets Beispiel Button wird gedrückt: btn.setonaction(new EventHandler<ActionEvent>() { @Override public void handle(actionevent arg0) { System.out.println("Button was pressed"); } }); Anderes Beispiel: setoncloserequest(windowevent ) Sogenannte Convenience-Methods, siehe: https://docs.oracle.com/javase/8/javafx/eventstutorial/convenience_methods.htm Programmiermethodik - GUI-Programmierung 37
Event-Arten ActionEvent Benutzer klickt z.b. einen Button an, drückt die Enter-Taste in einem Textfeld oder wählt einen Menüeintrag aus. InputEvent Benutzer drückt Maustaste, Tastatur-Taste. KeyEvent (Subklasse von InputEvent) Benutzer klickt eine Maustaste während der Mauszeiger über einer Komponente ist. MouseEvent (Subklasse von InputEvent) Benutzer bewegt die Maustaste über einer Komponente, drag and drop, Maustasten drücken. TouchEvent User bedient Applikation mittels Touch-Eingabe. WindowEvent Fenster wird maximiert, minimiert, skaliert. Programmiermethodik - GUI-Programmierung 38
Beispiel Mausklick auf Button Der Mausklick führt dazu, dass der Button ein Ereignis vom Typ ActionEvent erzeugt. Dieses Ereignis(-Objekt) hat alle Informationen über das Ereignis und seine Quelle und weiters eine Beschreibung der ausgeführten Aktion. Dieses Ereignis wird an alle bei dem Button registrierten ActionListener-Objekte geschickt. Jeder Listener implementiert eine Methode für die Ereignisbehandlung. In diesem Fall wird mit der Methode handle() festgelegt, was beim Eintreten des Ereignisses passieren soll. Damit ruft dann der Button bei einer Aktion (Mausklick) diesen Code auf! Programmiermethodik - GUI-Programmierung 39
MVC (Ausblick) Anstatt den gesamten Code in eine einzelne Klasse zu packen, werden beim MVC-Konzept drei unterschiedliche Bestandteile eines grafischen Elements unterschieden: Das Modell enthält die Daten des Dialogelements und speichert seinen Zustand. Die View ist für die grafische Darstellung der Komponente verantwortlich. Der Controller wirkt als Verbindungsglied zwischen beiden. Er empfängt Tastatur- und Mausereignisse und stößt die erforderlichen Maßnahmen zur Änderung von Model und View an. Beispiel TweetInspectorApplication.java Model: Tweet Controller: TweetInspectorController View: TweetInspectorUI Programmiermethodik - GUI-Programmierung 40
MVC View Controller Model bestimmt Darstellung bestimmt Inhalt des Models Programmlogik stellt Daten zur Verfügung TweetInspectorUI gibt Änderungen an das Model weiter TweetInspectorController Tweet Programmiermethodik - GUI-Programmierung 41
Beispiel TweetInspectorUI.java schon bekannt Tweet.java beinhaltet Tweet-Objekte TweetIO.java stellt statische Methoden zum Einlesen und Schreiben der Tweets von/in Files zur Verfügung TweetInspectorController.java verbindet UI und Model EventHandler für Buttons Löschen der Tabelleninhalte Schreiben der Inhalte der Tabelle in File Lesen aus File EventHandler für Menü Tabelleninhalt bestimmen Programmiermethodik - GUI-Programmierung 42
TableView TableView bietet Widgets zum Anzeigen von Tabellen Generische Implementierung Besteht aus einzelnen Spalten (TableColumn), die dem TableView hinzugefügt werden TableColumn<Tweet, String> coltext = new TableColumn<Tweet, String>("Text"); this.ui.gettabletweets().getcolumns().addall( Arrays.asList(colTweetID, coluser, coltext, colsource)); Programmiermethodik - GUI-Programmierung 43
TableView-Inhalt? Tabelleninhalt bestimmen List<Tweet> TableView<Tweet> Verbindung? Zuordnung zu Spalten? Programmiermethodik - GUI-Programmierung 44
TableView (3) TableView ist generisch getypt (<Tweet>) Klasse Tweet ist Model für die Tabelle Zuordnung Felder des Tweet-Objektes zu Spalten fehlt seit Java 1.8 vereinfacht, basiert auf Java Beans Tweet ist Bean Felder müssen per get<feldname> zugänglich sein Felder die Properties eines Objektes Bean schreibt diese Namenskonventionen vor Tweet-Felder sind Strings Felder als StringProperty Objekte Klare Schnittstelle Programmiermethodik - GUI-Programmierung 45
TableView (4) Klare Schnittstelle erlaubt einfaches Zugreifen auf Properties PropertyValueFactory() holt sich aus Daten, mit denen Tabelle gefüllt werden soll, mittels der Schnittstelle die Property tweettext Zuweisung an Tabellenzelle (setcellvaluefactory bestimmt, wie Zellen einer Tabelle gefüllt werden soll) coltext.setcellvaluefactory( new PropertyValueFactory<>("tweetText")); Programmiermethodik - GUI-Programmierung 46
TableView-Inhalt: ObservableList Spezielle Listen-Implementierung Benachrichtigt Listener über Änderungen Listener: TableView-Widget Unterliegt der TableView (setitems-methode) Änderung in data-objekt wirkt sich direkt auf TableView- Inhalt aus Event/Listener-Verhalten wird für Programmierer implizit übernommen durch Observable-Pattern // add example data this.data.add(new Tweet("this is an example tweet", "John Doe","TweetDeck", "2343957")); this.ui.gettabletweets().setitems(this.data); Programmiermethodik - GUI-Programmierung 47
Threads Die Ereignisbehandlung erfolgt immer im Event Dispatching Thread. Ein Event-Handler nach dem anderen. Auch die Zeichenroutinen der Komponenten laufen im Event Dispatching Thread ab. Während ein Event Handler abgearbeitet wird, ist die GUI eingefroren (reagiert nicht). Event Handler sollten immer nur wenig Rechenzeit verbrauchen! Langfristige Berechnungen müssen asynchron in extra Threads ausgeführt werden. Programmiermethodik - GUI-Programmierung 48
Ausblick: SceneBuilder Einfaches Designen von Uis Oracle liefert nur Sourcecode aus Standalone-Version von Gluon verfügbar Erzeugt eine FXML-Datei. FXML kann in Java dann mittels der FXMLLoader-Klasse geladen werden und bestimmt das Layout der Applikation. 49
Ausblick: SceneBuilder (2) Programmiermethodik - GUI-Programmierung 50
SceneBuilder FXML-Dateien Verwendung siehe HelloWorldApplication in package at.ac.uibk.dbis.informatik.gui.fxml Programmiermethodik - GUI-Programmierung 51
Ausblick JavaFX JavaFX kann noch viel mehr: Animationen Grafiken zeichnen Diagramme zeichnen CSS zum Stylen der Anwendung Im Browser laufen Gesten unterstützen für mobile Devices (Tablets, Smartphone) Programmiermethodik - GUI-Programmierung 52
Usability
Programmiermethodik - GUI-Programmierung 54
Programmiermethodik - GUI-Programmierung 55
Usability Benutzbarkeit Software-Ergnomie Leicht verständlich Schnell benutzbar Benutzer verwechseln oft Funktionalität mit GUI-Design Schlechte Usability führt zu Benutzungsfehlern oder schlimmer: der Nicht-Benützung der Software User-centered Design: User stets im Mittelpunkt des Designprozesses, auch durch Evaluation Programmiermethodik - GUI-Programmierung 56
Einfache Usability-Regeln Stay consistent The more users expectations prove right, the more they will feel in control of the system and the more they will like it. (Nielsen) Gleiches Verhalten, Positionierung von GUI-Elementen (z.b. Icons) User Control and Freedom Benutzer machen Fehler Möglichkeiten des Undo/Redo zu Verfügung stellen Speak their language Sprache und Konzepte verwenden, die dem Benutzer bekannt sind Methaphern (Einkaufswagen, Posteingang, Disketten-Symbol, etc.) Programmiermethodik - GUI-Programmierung 57
Einfache Usability-Regeln Provide feedback / Visibility of System Status User über aktuellen Status/Vorgehen informieren (Button gedrückt Action wird erwartet; immediate Gibt dem Benutzer das Gefühl, Herr/Frau der Lage zu sein Keep it simple A modern paradox is that it s simpler to create complex interfaces because it s so complex to simplify them. (Almquist) Programmiermethodik - GUI-Programmierung 58
Einfache Usability-Regeln Error prevention Dem User helfen, Fehler gar nicht zu begehen Beispiel: Email Attachments; Wertebereiche; auch: Previews Empower your user Unterscheidung Power-User und normale User (z.b. Tastaturbedienung, Tastaturkürzel oder setzbare Parameter (z.b. Google Bildsuche) Help users recognise and recover from errors Fehlermeldungen anbieten, die der User versteht Lösungen anbieten Stacktraces schüchtern ein! Help and documentation Programmiermethodik - GUI-Programmierung 59
Quellen Jakob Nielsen 1994: 10 Usability Heuristics for User Interface Design (https://www.nngroup.com/articles/ten-usability-heuristics/) Edgar Sibley 1990: Improving a Human-Computer Dialogue (http://heb.freeshell.org/ie662/molich_nielsen.pdf) http://blog.teamtreehouse.com/10-user-interface-designfundamentals http://de.slideshare.net/crafted/10-usability-heuristics-explained Bildquellen: http://www.iphonehacks.com/2013/12/ios-7-1-car-display-toggle-iosin-the-car.html http://www.bvspoker.com/images/tutorial/downloading.png http://www.actionoutline.com/ao_whatsnew.php Programmiermethodik - GUI-Programmierung 60