FXML, CSS RICHARD LIPKA 23.4.2018
Novinky v JavaFX PreferenecssFX Podpora pro dialogy s nastavením aplikace (Eclipse-like, se stromem a hledáním na levé straně) Automatická tvorba vstupních prvků pro nastavení 3D grafika v JavaFX Jednoduchý prohlížeč 3D Demo které vzniklo pro OpenJDK 23.4. 2018 UUR - FXML, CSS 2
XML (EXtensible Markup Language) Standardizovaný značkovací jazyk Zjednodušená podoba SGML Typicky pro serializaci dat (podobně jako JSON, YAML) Lze definovat vlastní značky (tagy) <znacka> </znacka> a atributy <znacka atribut= hodnota > </znacka> Značky se mohou vnořovat <znacka> <vnorena_znacka> </vnorena_znacka> <znacka> Jeden kořenový element, elementy se nesmí překrývat Stromová struktura, snadné zpracování obecnými nástroji 23.4. 2018 UUR - FXML, CSS 3
FXML XML soubor s definicí GUI Mapován přímo na volání z API vznikají všechny očekávané instance se kterými je možné manipulovat z Javy MVC Model: doménové objekty, JavaBeany, Propety View: FXML s definicí okna Controller: běžná Java ve které je vytvořena obsluha Hodí se pro Rychlý prototyping (nástroje pro WYSIWYG tvrobu) Složitá okna s velkými grafy scény Statické layouty formulářů + JavaScript lze tvořit i dynamické formuláře, manipulovat s prvky grafu přímo z FXML 23.4. 2018 UUR - FXML, CSS 4
Struktura FXML aplikace Zbytek aplikace Application.class Práce s modelem a GUI Controller.class Controller.class Controller.class Přistupuje/ zobrazuje Datový model Model.class načítá ovládá View.FXML View.FXML View.FXML Topologie GUI - View vzhled Style_1.CSS Style_2.CSS 23.4. 2018 UUR - FXML, CSS 5
Ukázka FXML <?import javafx.scene.layout.borderpane?> <?import javafx.scene.control.label?> <BorderPane> <top> <Label text="page Title"/> </top> <center> <Label text="some data here"/> </center> </BorderPane> 23.4. 2018 UUR - FXML, CSS 6
Hlavní výhody FXML Nutí k oddělení View od Controlleru Nemůžu nijak snadno vložit obsluhy přímo do View Viditelný graf scény Nemusím prohledávat třídy a metody které ho tvoří, vidím vše najednou XML jazyk Jednoduchý, snadno editovatelný (ručně i WYSIWYG), bez potřeby překládat snazší ladění (změny FXML se projeví i bez překladu zbytku aplikace pokud nezpůsobí chybu) Podpora lokalizace při načítání Textová data (popisky tlačítek, dialogů, ) se načítají při načítání XML při změně jazyka stačí znovu načíst FXML soubor Vzhled (odkaz na CSS) může být nastaven ve FXML souboru Použitelný ve všech jazycích založených nad JVM Scala, Clojure, Kotlin 23.4. 2018 UUR - FXML, CSS 7
Nevýhody FXML Menší kontrola nad aplikací JavaFX sestavuje aplikaci sama je těžší ovlivnit co se děje Občas neprůhledné nastavování parametrů Scene Builder generuje parametry které mohou způsobit divné chování Např. prefwidth= -1 vypočtená velikost, ale znemožní automatický resize sloupců Rozdělení projektu do mnoha souborů Problém pro začátečníky a lidi kteří mají chaos ve zdrojových textech Omezená nápověda XML nemá skutečné datové typy, je těžké odhadovat co lze kdy nastavit ne všechno co napoví Eclipse / IntelliJ bude i fungovat 23.4. 2018 UUR - FXML, CSS 8
Struktura Záhlaví standartní XML, důležité je kódování <?xml version="1.0" encoding="utf-8"?> Importy všechny třídy které jsou využity (jako v Javě) <?import javafx.scene.layout.borderpane?> Graf scény Jeden soubor jeden graf pro každé okno vlastní FXML (ve skutečnosti pro každý Node jde udělat FXML aplikaci z něj lze složit jako z fragmentů) Složen z hierarchicky strukturovaných tříd, tak jak by byl poskládán v Javě Obecná konvence Třídy jako v Javě (velké písmeno na začátku), každá instance jako jeden element Nastavení property malým písmenem (atribut nebo setter) 23.4. 2018 UUR - FXML, CSS 9
Tvorba objektů I Vytvoření nové instance Volání konstruktoru bez parametrů + nastavení Property přes setter Tvorba tlačítka: <Button mnemonicparsing="false" onaction="#removeitem prefheight="25.0" prefwidth="80.0" text="remove" GridPane.columnIndex="4 GridPane.halignment="CENTER" fx:id="addbt" /> Každý atribut odpovídá příslušnému setteru vznikne 1 instance třídy Button každý atribut se přeloží jako volání (pozor na typ!) Button addbt = new Button(); addbt.setmnemonicparsing(false); addbt.setprefheight(25.0); addbt.settext("remove"); 23.4. 2018 UUR - FXML, CSS 10
Tvorba objektů II Property lze nastavovat i jako samostatné značky Totéž jako předchozí příklad, jen jiný (delší zápis) Užitečné pokud Property není primitivní typ, ale třída <GridPane hgap="3.0" vgap="3.0" fx:id="pane"> <padding> <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> </padding> </GridPane> Přeloží se podobně, ale uvnitř značky může být konstrukce další třídy GridPane pane = new GridPane(); pane.setpadding(new Insets(5)); 23.4. 2018 UUR - FXML, CSS 11
Skládání grafu potomků Uložení potomků v grafu Uložení v kolekci dětí (getchildren()) FXML ji umí naplnit jako kdyby existovala property children (podobně fungují sloupce tabulky) Vložení potomků: <GridPane hgap="3.0" vgap="3.0"> <children> <Label text="name:" GridPane.rowIndex="1" /> <Label text="trip date" GridPane.columnIndex="1 GridPane.rowIndex="1" /> <Label text="trip:" GridPane.columnIndex="2 GridPane.columnSpan="2" /> <TextField fx:id="fromtf" GridPane.columnIndex="2" GridPane.rowIndex="2" /> <TextField fx:id="totf" GridPane.columnIndex="3 GridPane.rowIndex="2" /> </children> </GridPane> 23.4. 2018 UUR - FXML, CSS 12
Využití property pro skládání grafu Uložení potomků v grafu Uložení ve vlastních Property (BorderLayout.setCenter()) lze naplnit přes setter Vložení panelů do BorderPane: <BorderPane> <top> <MenuBar> </MenuBar> </top> <center> <TableView > </TableView> </center> <right> <TextArea> </TextArea> </right> <bottom> <GridPane </GridPane> </bottom> </BorderPane> 23.4. 2018 UUR - FXML, CSS 13
Tvorba jednoduchých property Lze vytvářet instance primitivních datových typů (stejně jako jiných objektů) využití fx:value <String fx:value="hello, World!"/> <Double fx:value="1.0"/> <Boolean fx:value="false"/> Property lze vkládat do kolekce získané přes její továrnu využití fx:factory pro třídy které nemají defaultní konstruktor <FXCollections fx:factory="observablearraylist"> <String fx:value="a"/> <String fx:value="b"/> <String fx:value="c"/> </FXCollections> 23.4. 2018 UUR - FXML, CSS 14
Využití property pro naplnění kolekcí Např. naplnění seznamů, výběrových seznamů a podobně <ListView> <items> <FXCollections fx:factory="observablearraylist"> <String fx:value="a"/> <String fx:value="b"/> <String fx:value="c"/> </FXCollections> </items> </ListView> 23.4. 2018 UUR - FXML, CSS 15
Volání statických metod Hodí se zejména u layoutů Nastavení pozice v layoutu, zarovnání a podobně Podobné jako settery staticky nastavené property <GridPane hgap="3.0" vgap="3.0"> <children> <Label text="trip:" GridPane.columnIndex="2" GridPane.columnSpan="2" fx:id="label" /> </children> </GridPane> Přeloží se jako GridPane pane = new GridPane(); Label label = new Label(); label.settext(); GridPane.setColumnIndex(label, 2); GridPane.setColumnSpan(label, 2); pane.getchildren.add(label); 23.4. 2018 UUR - FXML, CSS 16
Načtení dalších XML Hodí se při opakovaném užívání nějaké části XML Využívá fx:include <VBox xmlns:fx="http://javafx.com/fxml"> <children> <fx:include source="my_button.fxml"/> </children> </VBox> Vloží na místo fx:include obsah souboru (nahradí fx:include značku obsahem, přidá potřebné importy) Cesta relativní k souboru kde je použit (když začne / bude relativní ke classpath) 23.4. 2018 UUR - FXML, CSS 17
Provázání s Javou Načtení FXML přes resources FXMLLoader.load(getClass().getResource("experiment1.fxml")); Metoda typovaná na obecný objekt, vrací třídu odpovídající kořenovému grafu v souboru Typická tvorba okna: public void start(stage primarystage) throws Exception { primarystage.settitle("fxml TableView Example"); Pane mypane = (Pane)FXMLLoader.load (getclass().getresource("window.fxml")); Scene myscene = new Scene(myPane); primarystage.setscene(myscene); primarystage.show(); } 23.4. 2018 UUR - FXML, CSS 18
Nastavení obsluh Obsluhy je třeba napsat v Javě Každou obsluhu zajišťuje Controller K jednomu FXML může být přiřazen jeden nebo více Controllerů Určení Controlleru Uvnitř FXML elementu, pokud je jeden - obvykle v kořeni <BorderPane prefheight="437.0" prefwidth="659.0 xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="package.myfxmlcontroller"> fx:controller definuje třídu, která bude obsahovat obsluhy Uvnitř Controlleru lze získat reference na všechny entity z FXML Při načtení FXML 23.4. 2018 UUR - FXML, CSS 19
Získání reference na entitu Je nutné nastavit textový identifikátor elementu fx:id="myelement" pokud ho nenastavím, lze získat referenci jen analýzou potomků Jméno reference musí odpovídat id ve FXML dokumentu a musí být označen anotací @FXML loader zajistí nastavení reference Podpora v IDE detekuje jestli existují odpovídající entity FXML: <DatePicker fx:id="datedp" /> <TextField fx:id="nametf" /> Java: @FXML private TextField nametf; @FXML private DatePicker datedp; 23.4. 2018 UUR - FXML, CSS 20
Nastavení obsluhy Metoda obsluhy musí být definována v Controlleru tohoto nebo nadřazeného elementu Ve FXML jako normální setter, před jménem metody # V Javě metoda s odpovídajícím jménem která by byla uvnitř handleru Bez parametru nebo s odpovídající událostí FXML: <Button fx:id="addbt" onaction="#additem" /> Java: @FXML private TableView<Data> table; @FXML public void additem(actionevent event) { table.getitems().add(new Data()); } 23.4. 2018 UUR - FXML, CSS 21
Nastavení obsluhy s JavaScriptem Obsluha může být přímo v FXML dokumentu Pak se ale narušuje MVC model Lze využít JavaScript JRE mu rozumí a umí ho interpretovat Do deklarace přidat: <?language javascript?> Do obsluhy lze vložit samotný JavaScript: <VBox> <children> <Button text="click Me!" onaction="java.lang.system.out.println('message');"/> </children> </VBox> 23.4. 2018 UUR - FXML, CSS 22
Vlastní třídy buňky a továrny Nezbytné pro složené objekty tabulky, seznamy, Továrna na buňky je Property nastavena setterem: <TableView fx:id="triptv" editable="true"> <columns> <TableColumn text="name" oneditcommit="#commitname"> <cellvaluefactory> <PropertyValueFactory property="name"/> </cellvaluefactory> <cellfactory> <TextFieldFactory /> </cellfactory> </TableColumn> <TableColumn prefwidth="75.0" text="trip date" /> <TableColumn prefwidth="75.0" text="trip" /> </columns> </TableView> 23.4. 2018 UUR - FXML, CSS 23
Vlastní třídy získání hodnoty <TableColumn text="name" oneditcommit="#commitname"> <cellvaluefactory> <PropertyValueFactory property="name"/> </cellvaluefactory> Vytvoří už známou továrnu pro tvorbu Property ze zadaného atributu - odpovídá volání namecolumn.setcellvaluefactory (new PropertyValueFactory<Person, String>("name")); 23.4. 2018 UUR - FXML, CSS 24
Vlastní třídy tvorba buňky <?import package.textfieldfactory?> <TableColumn text="name" oneditcommit="#commitname"> <cellfactory> <TextFieldFactory /> </cellfactory> Musí existovat odpovídající továrna importovaná do FXML Buňka vytvářená ve factory v FXML není nijak vidět (pokud nemá svou statickou továrnu) public class TextFieldFactory <Person, String> implements Callback<TableColumn<Person, String>, TextFieldCell> { } public TextFieldCell call(tablecolumn<person, String> param) { return new TextFieldCell(); } 23.4. 2018 UUR - FXML, CSS 25
Odbočka 1- Novinky v JavaFX (23.4. 2018) RichTextFX Editor formátovaného textu (náhrada za HTMLEditor) Podpora zvýrazňování syntaxe Podpora CSS pro obsah text uvnitř (včetně pěkné dokumentace o tom jak ji udělat) Využit v řadě aplikací (Kappa IDE, BlueJ, ) UndoFX Podora pro undo/redo operace v JavaFX Snadná implementace pro každou property umí je sledovat Založen na ReactFX Framework pro reaktivní programování (obecně víc bindingu) GraphStream Knihovna pro zobrazení grafů Rozhraní pro JavaFX a Swing 23.4. 2018 UUR - FXML, CSS 26
Odbočka 2 Java a String String v Javě vždy neměnný (immutable) zjednodušuje a urychluje práci VM Platí pro objekty obsah řetězce, ne pro reference ty mohou ukazovat pokaždé jinam Všechny metody a operátory vždy vytváří nový objekt Existuje String Pool oblast paměti kde se řetězce vytvářejí, pevně daná hashmapa Stringové literály (literal = literal ;) jsou v něm automaticky normální objekty vytvářeny v heapu, ale mohou být přesunuty do String Poolu ručně (metoda String.intern()) Časově náročné metoda musí spravovat kolekci unikátních řetězců a hledat v ní Pokud je String získán jako parametr metody, není poznat kde je uložen String vždy chápat jako objekt, ne jako primitivní typ, pokud si nejsem jistý že vím co dělám (optimalizace rychlosti) Pro porovnání existuje řada metod (compareto(), comparetoignorecase(), equalsignorecase(), ) 23.4. 2018 UUR - FXML, CSS 27
Odbočka 2 Java a String public boolean equals(object anobject) { } if (this == anobject) { return true; } if (anobject instanceof String) { String anotherstring = (String)anObject; int n = value.length; if (n == anotherstring.value.length) { char v1[] = value; char v2[] = anotherstring.value; int i = 0; while (n--!= 0) { if (v1[i]!= v2[i]) return false; i++; } return true; } } return false; 23.4. 2018 UUR - FXML, CSS 28
Odbočka 2 Java a String String a = "a"; String b = "a"; System.out.println(a == b); System.out.println(a.equals(b)); true true a b Heap "a" String Pool 23.4. 2018 UUR - FXML, CSS 29
Odbočka 2 Java a String String a = new String("a"); String b = "a"; System.out.println(a == b); System.out.println(a.equals(b)); false true a b Heap "a" "a" String Pool 23.4. 2018 UUR - FXML, CSS 30
Odbočka 2 Java a String String a = new String("a"); String b = "a"; System.out.println(a == b); System.out.println(a.equals(b)); a = a.intern(); true a b Heap "a" true "a" String Pool 23.4. 2018 UUR - FXML, CSS 31
String Pool a GC Do Java 6 umístěn v PermGen oblasti paměti žádná garbage kolekce Potenciální zdroj memory leaků na starších JVM Nejde je odstranit, jen změnit velikost PermGen aby stačila Od Java 7 umístěn v heapu GC funguje Internalizovaný String je pořád objekt jako každý jiný Stringové literály (literal = literal ;) mají (téměř pozor na dynamické classloadery) vždy implicitní referenci nikdy nejsou odstraněny během GC Od Java 8 (8u20) je v G1 GC String Deduplication (od Java 9 defaultní GC) Protože pole znaků ve Stringu nelze měnit, mělo by být bezpečné ho sdílet i v rámci heapu -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics -XX:StringDeduplicationAgeThreshold=3 Zapne GC G1 Povolí String Deduplication GC vypisuje statistiky String Deduplication Nastavuje od jakého stáří objektu je String Deduplication povolena (drahá operace) 23.4. 2018 UUR - FXML, CSS 32
CSS Založen na standartu W3C CSS version 2.1 Umožňuje definovat vzhled (ne strukturu) okna Barvy Fonty Rámečky Obrázky na pozadí Pozice Snadná změna vzhledu výměnou CSS souborů Velmi podrobný dokument s kompletní specifikací: http://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html 23.4. 2018 UUR - FXML, CSS 33
CSS v Javě Všichni potomci Node mají metodu setstyle(string) Každému elementu lze v programu nastavit vzhled Základní tlačítko Nastavený styl hello01bt.setstyle("-fx-text-fill: #006464;" + " -fx-background-color: #DFB951;" + " -fx-border-radius: 20;" + " -fx-background-radius: 20;" + " -fx-padding: 5;"); 23.4. 2018 UUR - FXML, CSS 34
Načtení Nastavovat každému uzlu vlastní styl je nepraktické načtení stylu: Ze souboru: String css = MyClass.class.getResource("mycss.css"); scene.getstylesheets().clear(); scene.getstylesheets().add(css); Z URL: scene.getstylesheets().clear(); scene.getstylesheets().add("http://www.url/css/mycss.css"); Ve scéně může být nastaveno několik CSS Košile bližší než kabát CSS nastavené uzlu překryje CSS scény 23.4. 2018 UUR - FXML, CSS 35
Selektory Umožňují propojit styl s uzlem grafu ( adresování ) ID unikátní identifikátor uzlu (fx:id nebo setid()) Nastavení vzhledu tohoto konkrétního uzlu #nodeid { -fx-fill: red; } Třída uzel může mít přiřazeno několik tříd (getstyleclass.addclass("name")) Nastavení vzhledu všech prvků dané třídy Uzel má vždy alespoň třídu odpovídající jeho typu (TableView tableview).label { -fx-text-fill: black; } 23.4. 2018 UUR - FXML, CSS 36
Selektory Pseudotřída podobné jako třída, obvykle dynamicky určená (metoda getpseudoclassstate() vrací aktuální kolekci) Stav uzlu, pozice myši, výběr v tabulce - často odpovídají nějaké Property Použití stejné jako u tříd Všichni mají: disabled focused hoover pressed Další pseudotřídy podle typu uzlu odd, even Selected V dokumentaci k CSS podrobný popis pseudotříd pro každý uzel 23.4. 2018 UUR - FXML, CSS 37
Selektory Použití pseudotříd Jen ve spojení s jinou třídou.label:hover { fx-text-fill: green; } Lze je kombinovat.button:hover:pressed { -fx-text-fill: white; } 23.4. 2018 UUR - FXML, CSS 38
Adresování složený selektor Nastavení prvků uvnitř jiného prvku 2 panely, v každém chci jinou barvu tlačítek nestačí třída button Můžu každému tlačítku dát další třídu, ale pak může dojít k nekonzistenci při přesunu tlačítka Lze použít složený selektor ancestor offspring {} Styl ovlivní jen potomky (offspring) uvnitř předka (ancestor), jinde nemá vliv #pane1.button {} #pane2.button {} Pro přímé potomky jako oddělovač > 23.4. 2018 UUR - FXML, CSS 39
Nastavitelné vlastnosti Záleží na uzlu který je nastavován Uzly dědí nastavitelné vlastnosti a pseudotřídy U vlastností prefix fx- pro odlišení od běžného CSS Syntaxe nastavení vlastnosti: Vlastnost : hodnota; -fx-border-radius: 20; CSS používá datové typy vlastnosti mají určeno jakého typu budou hodnoty Číselné vlastnosti mohou vyžadovat uvedení jednotek (např. rozměr) 23.4. 2018 UUR - FXML, CSS 40
CSS a pozice V normálním HTML lze ovlivnit místo prvku na obrazovce V JavaFX o tom rozhoduje layout jen omezené možnosti Povolené vlastnosti: padding margin Nepoužité vlastnosti: float position overflow width height 23.4. 2018 UUR - FXML, CSS 41
Vybrané datové typy Primitivní typy: boolean, string, number Měřitelné typy: size, angle Relativní jednotky (px, em, ex) Absolutní jednotky (in, cm, mm, pt, pc) nemusí fungovat správně Obvykle 3pt = 4px (96 ppi) Úhly (deg, rad, grad, turn) Složené typy: font, color, paint Typy složené z několika primitivních nebo složených atributů Existují funkce pro jejich sestavení Nemusí být nastaveny všechny atributy 23.4. 2018 UUR - FXML, CSS 42
Typ Font Atributy font-family rodina, jméno fontu nebo skupiny fontů (serif / sansserif / font_name) font-size velikost, v zadaných jednotkách (pt, px) font-style nastavení kurzívy (normal / italic / oblique) font-weight nastavení tučnosti (normal / bold / bolder.) Příklad nastavení fontu a jednotlivých atributů.custom-button { -fx-font: bold 16px "Serif"; }. custom-button { -fx-font-size: 16pt; -fx-font-family: "Courier New"; } 23.4. 2018 UUR - FXML, CSS 43
Typ Color Nastavení barvy Podporuje RGB model Řada barev má definované jméno.button { -fx-background-color: red; }.button { -fx-background-color: #87ceeb; } Lze dohledat barvu nastavenou jako konstantu (looked-up color).root { abc: #f00 }.button { -fx-background-color: abc } Funkce pro sestavení z RGB hodnot -fx-border-color: rgb(49, 89, 23); 23.4. 2018 UUR - FXML, CSS 44
Vlastnosti Region Vlastnosti kolem pozadí a orámování Atributy background-color barva pozadí padding odsazení od okrajů border-color, border-radius, border-style, border-width nastavení rámečku kolem oblasti border-style ovlivňuje typ čáry (solid, dotted, dashed, ridge, inset ) Příklad.button{ -fx-border-color: rgb(49, 89, 23); -fx-border-radius: 5; -fx-border-style: solid; -fx-padding: 3 6 6 6; } 23.4. 2018 UUR - FXML, CSS 45
Styly rámečků solid dotted dashed double groove ridge inset outset none hodnoty příklad 23.4. 2018 UUR - FXML, CSS 46
Vlastnosti Labeled Všechny ovládací prvky s popiskem (Label, Button, ) Atributy: alignment zarovnání uzlu vůči rodiči text-alignment zarovnání textu wrap-text povoluje / zakazuje zalamování textu font font kterým se popisek vypisuje text-fill barva textu underline nastavuje podtržení Příklad:.label { -fx-font-size: 20pt; -fx-font-family: "Segoe UI Light"; -fx-text-fill: white; -fx-alignment: center-left; -fx-opacity: 1; } 23.4. 2018 UUR - FXML, CSS 47
Děkuji za pozornost OTÁZKY? NÁZORY, PŘIPOMÍNKY? PŘÍŠTĚ: TESTOVÁNÍ