Seznam, tabulka, strom

Podobné dokumenty
UJO Framework. revoluční architektura beans. verze

Generické programování

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Zapouzdření. Tomáš Pitner, upravil Marek Šabo

typová konverze typová inference

Výčtový typ strana 67

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Semestrální práce 2 znakový strom

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

20. Projekt Domácí mediotéka

Java - řazení objektů

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Úvod do programovacích jazyků (Java)

Java a XML. 10/26/09 1/7 Java a XML

8 Třídy, objekty, metody, předávání argumentů metod

IRAE 07/08 Přednáška č. 1

Dědění, polymorfismus

GUI. JavaFX. Java UI, letní semestr 2017/2018 1

Teoretické minimum z PJV

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

1. Téma 12 - Textové soubory a výjimky

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

NPRG031 Programování II 1 / :25:46

NMIN201 Objektově orientované programování 1 / :36:09

OMO. 4 - Creational design patterns A. Singleton Simple Factory Factory Method Abstract Factory Prototype Builder IoC

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

11 Diagram tříd, asociace, dědičnost, abstraktní třídy

Abstraktní datové typy: zásobník

KTE / ZPE Informační technologie

Ovládání Open Office.org Calc Ukládání dokumentu : Levým tlačítkem myši kliknete v menu na Soubor a pak na Uložit jako.

Kolekce, cyklus foreach

boolean hasnext() Object next() void remove() Kolekce

Uživatelský manuál. Aplikace GraphViewer. Vytvořil: Viktor Dlouhý

Jazyk C# (seminář 6)

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Programování v C++ 2, 4. cvičení

KOMPONENTY APLIKACE TreeINFO. Petr Štos ECM Business Consultant

TÉMATICKÝ OKRUH Softwarové inženýrství

Třídy. Instance. Pokud tento program spustíme, vypíše následující. car1 má barvu Red. car2 má barvu Red. car1 má barvu Blue.

Generické typy. Podrobněji: The Java Language Specification ( Third Edition ) , 18

Google Web Toolkit. Martin Šurkovský, SUR března Katedra informatiky

NetBeans platforma. Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti

Programování v Javě I. Leden 2008

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Abstraktní třída a rozhraní

Programování v Javě I. Únor 2009

Algoritmizace prostorových úloh

1. Programování proti rozhraní

Seminář Java IV p.1/38

Při studiu tohoto bloku se předpokládá, že student je zvládá základy programování v jazyce Java s využitím vývojového prostředí NetBeans.

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

1. Dědičnost a polymorfismus

Základy objektové orientace I. Únor 2010

Technologie JavaBeans

Tematický celek Proměnné. Proměnné slouží k dočasnému uchovávání hodnot během provádění aplikace Deklarace proměnných

Platforma Java. Petr Krajča. Katedra informatiky Univerzita Palackého v Olomouci. Petr Krajča (UP) KMI/PJA: Seminář V. 27. říjen, / 15

Stromy. Příklady. Rekurzivní datové struktury. Základní pojmy

Přehledy pro Tabulky Hlavním smyslem této nové agendy je jednoduché řazení, filtrování a seskupování dle libovolných sloupců.

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Datové typy v Javě. Tomáš Pitner, upravil Marek Šabo

KMI / TMA Tvorba mobilních aplikací. 9. seminář ZS 2016/2017 Středa 13:15-15:45

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Mediator motivace. FontDialog. závislosti mezi jednotlivými ovládacími prvky jsou netriviální

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Dynamické datové struktury I.

Vstupní požadavky, doporučení a metodické pokyny

Tvorba informačních systémů

public static void main(string[] args) { System.out.println(new Main().getClass().getAnnotation(Greet.class).text());

Programování v C++ 3, 3. cvičení

Obsah. Úvod 11 Základy programování 11 Objektový přístup 11 Procvičování 11 Zvláštní odstavce 12 Zpětná vazba od čtenářů 12 Errata 13

Student s Life. Návrhová dokumentace (Design) Lukáš Barák, Jakub Ječmínek, Jaroslav Brchel, Jiří Zmeškal

JAVA JavaBeans Java, letní semestr 2018

Programování v jazyku C# II. 5.kapitola

Tabulka symbolů. Vazba (binding) Vazba - příklad. Deklarace a definice. Miroslav Beneš Dušan Kolář

Základní datové struktury

První kapitola úvod do problematiky

Vzorce. StatSoft. Vzorce. Kde všude se dá zadat vzorec

Programování v C++ 1, 5. cvičení

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

PŘETĚŽOVÁNÍ OPERÁTORŮ

Uživatelský manuál aplikace. Dental MAXweb

Obsah přednášky. 12. Dokumentace zdrojového kódu Tvorba elektronické dokumentace UML. Co je diagram tříd. Ing. Ondřej Guth

Fronta (Queue) Úvod do programování. Fronta implementace. Fronta implementace pomocí pole 1/4. Fronta implementace pomocí pole 3/4

Vytvořil Institut biostatistiky a analýz, Masarykova univerzita J. Jarkovský, L. Dušek, M. Cvanová. 5. Statistica

Zpravodaj. Uživatelská příručka. Verze

Vytváření a použití knihoven tříd

Komponenty v.net. Obsah přednášky

Úvod...1 Instalace...1 Popis funkcí...2 Hlavní obrazovka...2 Menu...3 Práce s aplikací - příklad...5

Programátorská příručka

ZSF web a intranet manuál

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

43 HTML šablony. Záložka Šablony v systému

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

TÉMATICKÝ OKRUH Softwarové inženýrství

JAVA. Další jazyky kompilovatelné do Java byte-code

Tabulkový procesor. Základní rysy

5 Rekurze a zásobník. Rekurzivní volání metody

VKLÁDÁNÍ OBJEKTŮ - tabulka

WR Reality. Web Revolution. Uživatelský manuál administračního rozhraní

Transkript:

Seznam, tabulka, strom RICHARD LIPKA 3.4.2017

Properties JavaBean třída, která nese data objektu Všechny atributy neveřejné (private) Přístup k atributům přes get (), set (), is () a Bean() metody stejné jméno jako atribut Takový atribut se označuje jako Property (vlastnost) Snadný automatický přístup podle jména (viz CellValueFactory a podobné objekty později) Sousta automaticky generovaného kódu využít prostředky IDE Konstruktor bez parametrů Po vytvoření je objekt neinicializovaný, nutné ho nastavit jeho settry JavaBean by měla být schopna naslouchat událostem a generovat zprávy pro ostatní objekty Observable observer pattern V Jave API pro tvorbu JavaBean java.beans package, javafx.beans package použití v JavaFX

JavaFX beany - Property Velmi často použity pro reprezentaci dat (modely) Označovány jako Property slouží jako atributy metod JavaFX Obvykle typováno na data která jsou v Property uložena Mohou mít přiřazené jméno Umožňují sledování svých hodnot, potomek Rozhraní Observable, ObservableValue<T> - manipulace s posluchači, získání hodnoty Rozhraní WritableValue<T> pro zápis a získání hodnoty Rozhraní Property<T> pro binding spojení hodnot dvou objektů Implementace hotové třídy pro všechny základní objekty Property, ReadOnly Property abstraktní Simple Property lze vytvářet instance, má inicializační konstruktory

Simple Property Primitivní datové typy typované na příslušný typ SimpleBooleanProperty SimpleDoubleProperty SimpleFloatProperty SimpleIntegerProperty SimpleLongProperty Objekty SimpleStringProperty SimpleObjectProperty nastavení většiny vlastností JavaFX objektů (pozice, zarovnáni, editovatelnost, sloupce tabulky,.) Kolekce typované na typ dat v kolekci SimpleListProperty<E> implementuje ObservableList<E> SimpleMapProperty<K, V> SimpleSetProperty<E>

Definice vlastní property (?abstract?) class Account { private DoubleProperty amountdue = new SimpleDoubleProperty(); nejde překrýt potomek ji musí využít public final double getamountdue() { return amountdue.get(); public final void setamountdue(double value){ amountdue.set(value); public DoubleProperty amountdueproperty() { return amountdue;

Práce s vlastní property Data zapouzdřena v objektu odvozeném z Simple Property všechny změny prováděny v něm Lze snadnou naslouchat jeho změnám Account personalaccount = new Account(); personalaccount.amountdueproperty().addlistener(new ChangeListener(){ public void changed(observablevalue o, Object oldval, Object newval){ System.out.println( Account has changed!"); );

Binding Umožňuje provázat dvě Property, tak aby se změna jedné projevila Základní propojení Metoda bind(observablevalue()) int1.bind(int2) změna int2 se projeví v int1 (stejná hodnota getvalue()) int1 nemohu nastavit jen ukazuje na int2 Property ví jestli je jen svázaná (int1) nebo jestli obsahuje hodnotu (int2) Lze testovat přes isbound() jen int1 je svázaná Obousměrné propojení Metoda bindbidirectional(property) int1.bindbidirectional(int2) mohu měnit int1 i int2 a změna se propaguje oběma směry

Skládané objekty High level API Lze vytvářet objekty třídy Bindings, které obsahují automaticky aktualizovaný výsledek vzorce IntegerProperty num1 = new SimpleIntegerProperty(1); IntegerProperty num2 = new SimpleIntegerProperty(2); NumberBinding sum = num1.add(num2); V sum bude vždy součet num1 a num2 sum lze použít pro sestavení dalších vzorců NumberBinding mult = sum.multiply(num2) API obsahuje metody pro všechny základní aritmetické operace

Skládané objekty Low level API Pokud nestačí základní aritmetika je možné definovat si vlastní vzorce Sada tříd Binding pro primitivní číselné typy V inicializačním bloku je nutné nastavit všechny Property použité pro výpočet Inicializační blok statický nebo dynamický, dynamický vložen do každého konstruktoru V metodě computevalue() samotný výpočet DoubleProperty a = new SimpleDoubleProperty(1); DoubleProperty b = new SimpleDoubleProperty(2); DoubleBinding db = new DoubleBinding() { { super.bind(a, b, c, d); protected double computevalue() { return (Math.sin(a.get()) * Math.cos(b.get())); ;

Seznam (ListView<T>) Zobrazení seznamu Typováno typ položek v modelu který je zobrazován Zobrazuje model Spojen s ObservableList<T> Pro výpis použita metoda tostring() ListView<String> listview = new ListView<String>(); ObservableList<String> items = FXCollections. observablearraylist ("Single", "Double", "Suite", "Family App"); list.setitems(items); Lze nastavit vertikální nebo horizontální podobu

Druhy výběru (SelectionModel) Nastavení co je možné vybrat getselectionmodel().setsele ctionmode(selectionmode) SelectionModel.SINGLE SelectionModel.MULTIPLE Získání vybraných prvků getselectionmodel(). getselectedindices() seznam indexů getselecteditems() seznam prvků Vrácené seznamy aktualizované, jen pro čtení

Zpracování výběru Od verze 8.40 funguje, opraveno removeall(collection) i s částí téže kolekce V čemkoliv starším se to bude chovat divně musíte provést mazání s kopií ObservableList<Person> selectioncopy = FXCollections.observableArrayList (personview.getselectionmodel().getselecteditems()); Mazání označeného prvku posouvá označení personview.getselectionmodel().clearselection(); Při čtení výběru problémy nejsou

Přidávání prvků Vkládat do původní kolekce ListView se aktualizuje automaticky Pokud není dostupná, lze ji získat přes getitems() Metody add(item) add(index, Item) posouvá zbytek kolekce, index musí být uvnitř stávající kolekce addall(collection) vkládání celé další kolekce

Buňka Dostane prostor uvnitř seznamu a může ho využít podle sebe Defaultně implementována pomocí Label / TextField Musí rozumět datům které zobrazuje nebo upravuje a být s nimi propojena Defaultně využívá tostring() nebo binding, pokud je to možné Musí umět zobrazit prázdný řádek (doplnit komponentu) Dva režimy Zobrazovací (renderer) vykreslení dat tostring() převádí data do zobrazitelné podoby Editační (editor) úprava dat, vstup od uživatele Je možné data získat z textového / poskytnutého vstupu? Komponenta zajišťuje přepínání režimů, implementace buňky musí zajistit zobrazení Pozor, na akce které přepínání režimů obejdou / nevynutí

Buňky (ListCell<T>) Každý řádek je vykreslován jednou buňkou Typovány na obsah, stejně jako ListView Je možné vytvořit vlastní buňku Musí být potomek ListCell, hodí se znát typ dat která má zobrazovat private class MyCell extends ListCell<Person> { public void updateitem(person item, boolean empty) { super.updateitem(item, empty); if (item!= null) { settext(item.getname()); personview.setcellfactory(new Callback<ListView<Person>, ListCell<Person>>() { public ListCell<Person> call(listview<person> param) { return new MyCell(); );

Editovatelné buňky (pro String) Připraveno několik typů buněk (CheckBoxListCell, ComboBoxListCell, TextFieldListCell, ) a pro ně továrny Je možné je použít rovnou Má defaultní implementaci pro uložení hodnoty do kolekce, lze překrýt vlastní obsluhou Použití s kolekcí String personview.setcellfactory(textfieldlistcell.forlistview()); personview.seteditable(true); personview.setoneditcommit(event -> personview.getitems().set(event.getindex(), event.getnewvalue())); personview.setoneditcancel(event -> {);

Editovatelné buňky Pokud v seznamu není String, lze použít StringConverter<T> Potřebuje metody tostring() i fromstring() personview.seteditable(true); personview.setcellfactory(textfieldlistcell.forlistview (new StringConverter<Person>() { public Person fromstring(string string) { return new Person(string); )); public String tostring(person object) { return object.getname(); Pozor, konvertor nemá referenci na ukládané objekty vytváří nový! Ve vlastní obsluze je možné ho využít k nastavení změněné hodnoty

Vlastní buňka CellFactory může vracet libovolnou buňku, může vracet různé buňky podle objektů v seznamu Platí pro seznamy, tabulky i stromy stejné buňky Je potřeba překrýt implementaci public void updateitem(t item, boolean empty)- vznik buňky pro vykreslení Minimálně tohle je třeba překrýt vždy Testovat jestli v item něco je public void startedit() vznik buňky pro editaci Přes setgraphics() lze vložit vlastní uzel provádějící editaci Je třeba zajistit reakci na potvrzení editace (ENTER) volat commitedit(t) public void canceledit() obnovení stavu po editaci Nezapomenout odstranit grafiku editace

Tabulka (TableView<S>) Zobrazení strukturovaných dat Vnitřně složena ze sloupců (TableColumn), řádek (TableRow) a buněk (TableCell) Sloupce se dají vnořovat do sebe Model založený na ObservableList<S> Je třeba zajistit mapování sloupců na položky v kolekci Tabulka typována na typ obsahu Lze nastavit table.getselectionmodel().setselectionmode (SelectionMode.MULTIPLE);

Sloupce (TableColumn<S, T>) Sloupce se definují při tvorbě tabulky Typovány na typ obsahu tabulky a sloupce TableView table = new TableView(); TableColumn firstnamecol = new TableColumn("First Name"); TableColumn emailcol = new TableColumn("Email"); TableColumn firstemailcol = new TableColumn("Primary"); TableColumn secondemailcol = new TableColumn("Secondary"); emailcol.getcolumns(). addall(firstemailcol, secondemailcol); table.getcolumns(). addall(firstnamecol, emailcol);

Datový model V kolekci musí být objekty s metodami get() a set() pro všechny zobrazované atributy Java Bean neveřejné atributy, veřejné getry a setry, bezparametrický konstruktor, serializovatelné; ideálně Property Nám stačí getry, setry a property Nastavení modelu přes setitems() Pro každý sloupec je třeba nastavit zdroj dat setcellvaluefactory<s, T>(property) firstnamecol.setcellvaluefactory (new PropertyValueFactory<Person, String>("name")); z name automaticky dohledá getname() metodu a využije ji k nastavení hodnoty v buňce (reflexe) Pokud metoda neexistuje, nic se nestane ( těžší hledání chyb)

Datový model - ukázka public class Person { private StringProperty name; public Person(String name) { super(); this.name = new SimpleStringProperty(name); public final String getname() { return name.get(); public final void setname(string name) { this.name.set(name);; public StringProperty nameproperty() { return name;

Datový model - property Pozorovatelné kdokoliv ví o jejich změnách Property slouží jen jako wrapper kolem skutečných dat Základní property jednoduché (uvnitř jen jedna proměnná) Složitější s objektovými property SimpleObjectProperty<T> Wrapper kolem objektu T Reaguje jen na vložení nového objektu SimpleListProperty<T> Potřebuje v konstruktoru dostat ObservableList<T> s prvky T Reahuje jen na vložení dat do seznamu, ne na změny dat uvnitř T

Řazení ve sloupci Tabulka automaticky řadí data ve sloupcích Po kliknutí na záhlaví sloupce Přirozené řazení, podle typu dat ve sloupci Řazení lze ovlivnit setsortable(false) zakáže / povolí řazení setsorttype(tablecolumn.sorttype.descending) nastavení směru řazení Sloupci lze nastavit komparátor setcomparator(comparator<t>) Má přístup jen k datům sloupce tomu co získá z CellValueFactory Nahrazuje výchozí komparátor

Chování tabulky Rozšiřování Tabulka umí vyplnit dostupný prostor tabletv.setcolumnresizepolicy( TableView.CONSTRAINED_RESIZE_POLICY); UNCONSTRAINED_RESIZE_POLICY Lze si napsat vlastní ResizePolicy nutné pro každý sloupec sestavit ResizeFeature<S> s jeho velikostí většinou stačí výchozí policy Řazení celé tabulky Lze provádět přes řazení kolekce FXCollections.sort(tableView.getItems()) Lze nastavit styl řazení (setsortpolicy()) Callback ve kterém se vyvolá řazení Užitečné pokud má řazení zajistit někdo jiný (databáze)

Editace buněk Funguje podobně jako u ListView Nutné nastavit buňky podporující editaci firstnamecol.setcellfactory (TextFieldTableCell.forTableColumn()); Nastavení obsluhu při úpravě buňky (není nutné při použití property) firstnamecol.setoneditcomit(event -> { ((Person) event.gettableview().getitems().get( event.gettableposition().getrow()) ).setname(event.getnewvalue()); ); Pozor, bez nastavení obsluhy se změna sice propaguje do buňky (u předem připravených buněk), ale ne do modelu Pozor, lambda výrazy fungují jen pokud jsou sloupce důsledně typovány (event je typu <CellEditEvent<Person, String>> )

Existující buňky (potomci TableCell) Potomci IndexedCell Lze získat index (pořadí v kolekci) getindex() Pro sudost a lichost také rozhraní Stylable getpseudoclassstates().contains (PseudoClass.getPseudoClass("even")) (PseudoClass.getPseudoClass("odd")) Existující buňky a továrny CheckBoxTableCell ChoiceBoxTableCell ComboBoxTableCell ProgressBarTableCell TextFieldTableCell Obecně typované nemusí zobrazovat String, ale jakýkoliv objekt (stejný typ jako sloupec!) U textových je možné nastavit StringConverter, u seznamů seznam položek (tovární metoda fortablecolumn()) Updatují automaticky editor a renderer, ale ne datový model!

Vytvoření vlastní buňky Potomek TableCell<S, T> Rovnou typovat na data která má zobrazovat (může být napsána obecně - složitější) Vždy má textové pole pro zobrazení řetězce (Label) Spojena se zobrazovaným prvkem (getitem()) 2 režimy editační a zobrazovací TableCell umí zajistit přepínání Zajistit zobrazení vlastních komponent typicky má privátní editor a renderer (nebo jen editor) Je třeba zajistit Načtení dat z modelu Zobrazení správné komponenty v obou režimech Nastavení dat do editační a zobrazovací komponenty Propagaci dat z buňky do modelu

Kostra buňky Vlastní editor a obsluha jeho událostí rozhodnutí o commit a cancel public class TextFieldCell extends TableCell<Person, String>{ private TextField texttf; private void createeditor() { texttf = new TextField(); texttf.setonkeyreleased(event -> { if (event.getcode() == KeyCode.ENTER) { commitedit(texttf.gettext()); else if (event.getcode() == KeyCode.ESCAPE) { canceledit(); );

Vlastní buňka přepnutí režimů public void startedit() { super.startedit(); if (texttf == null) { createeditor(); settext(null); texttf.settext(createeditorcontent()); setgraphic(texttf); public void canceledit() { super.canceledit(); settext(createcontent()); setgraphic(null); private String createcontent() { return getindex() + " : " + getitem(); private String createeditorcontent() { return getitem();

Vlastní buňka - update public void updateitem(string item, boolean empty) { super.updateitem(item, empty); if (empty) { settext(null); setgraphic(null); else { if (isediting()) { if (texttf!= null) { texttf.settext(createeditorcontent()); settext(null); setgraphic(texttf); else { settext(createcontent()); setgraphic(null);

Vlastní továrna Rozhraní Callback<P, R> P parametr metody call(p) R návratový typ metody R call(p) Správně typovat P sloupec tabulky (TableColumn<RowData, CellData>) R buňka tabulky (TableCell<RowData, CellData>) namecolumn.setcellfactory (new Callback<TableColumn<Person,String>, TableCell<Person,String>>(){ public TableCell<Person, String> call (TableColumn<Person, String> column) { return new TextFieldCell(); ); namecolumn.setcellfactory(column -> {return new TextFieldCell(); );

Událost CellEditEvent<E, T> Typována na Položku tabulky (E), typ buňky / sloupce (T) Vzniká při Potvrzení editace (setoneditcomit()) Zrušení editace (setoneditcancel()) pokud jsou buňky editovatelné, je nutné na ni reagovat v obsluze uložit data do modelu Obsahuje Kde došlo k editaci - gettableposition(), v ní getrow(), getcolumn() Starou (getoldvalue()) a novou (getnewvalue()) hodnotu buňky (získanou při potvrzení commitu), aktuální hodnotu řádky (getrowvalue()) Tabulku kde došlo k události (gettableview())

Uložení dat do modelu Obsluha události CellEditEvent<E, T> Metoda setoneditcommit() (buňka nemá referenci na celý řádek, ale jen na svou hodnotu) namecolumn.setoneditcommit(event -> { comitname(event); ); private void comitname(celleditevent<person, String> event) { tabletv.getitems().get (event.gettableposition().getrow()).setname(event.getnewvalue()); // nebo event.getrowvalue(). setname(event.getnewvalue());

Manipulace s daty Přidávání do kolekce modelu Lze získat přes getitems() Tabulka automaticky aktualizována Získání vybraných dat selection = table.getselectionmodel().getselecteditems(); Mazání stejné jako u seznamu (probíhá nad kolekcí nezáleží na tom jestli jde o tabulku) Řádky Kontejner TableRow v sobě má buňky jednoho řádku, obvykle stačí výchozí Kontextové menu Dá se nastavit pro celou tabulku nebo pro každý sloupec zvlášť Vypočtené sloupce Data lze vytvářet v tovární metodě, v datovém modelu (získat přes get ()) nebo přes binding sestavení vlastní vypočtené property

Získání dat bez getrů Nutné vytvořit si vlastní továrnu na tvorbu dat Musí vracet implementaci ObservableValue<ColumnType> - obalové objekty Property<> pro všechny datové typy namecolumn.setcellvaluefactory( new Callback<TableColumn.CellDataFeatures<Person,String>, ObservableValue<String>>() { public ObservableValue<String> call (CellDataFeatures<Person, String> param) { return new SimpleStringProperty(param.getValue().getName()); ); namecolumn.setcellvaluefactory(celldata -> { return new SimpleStringProperty(cellData.getValue().getName()); ); CellDataFeatures<RowType, ColumType> obaluje hodnotu v jednom řádku, reference na tabulku, sloupec a data RowType getvalue()

Vypočtený sloupec connectednamecolumn.setcellvaluefactory(value -> new StringBinding() { { super.bind(value.getvalue().nameproperty(), value.getvalue().surnameproperty()); @Override protected String computevalue() { return value.getvalue().nameproperty().getvalue() + " " + value.getvalue().surnameproperty().getvalue(); );

Strom (TreeView<T>) Zobrazení stromových dat Složen z TreeItem<T> Jen obaluje uživatelský typ T není nutné řešit zařazení prvku do stromu Není Node, jen tvoří logickou strukturu stromu Ve stromu TreeCell<T> Sestavení podobné jako u grafu scény Jeden kořen Prvky mají potomky getchildren(), jako kolekci prvků stromu

Sestavení stromu Je nutné vytvořit dopředu alespoň kořenový uzel TreeItem<String> rootnode = new TreeItem<String>("MyTree"); TreeView<String> treeview = new TreeView<String>(rootNode); Další uzly je možné přidávat jako potomky getchildren().add() nebo addall() Uzly je možné programově expandovat rootnode.setexpanded(true) Expanduje se TreeItem, ne TreeCell! Uzel vykreslen přes tostring() metodu obalovaného objektu S každým prvkem stromu může být spojen Node vykreslí se před jeho popis

Zpracování prvků Podobné jako v seznamu Lze nastavit režim výběru pozor při výběru více prvků mohou být na různých místech ve stromu getselectionmodel().getselecteditems() vrací kolekci prvků typováno na <TreeItem<T>>, ne na samotné T Vkládat potomky za vybrané prvky jde snadno Stačí přidat jako jeho děti Mazání je složité Strom není jednoduchá kolekce nemá nic jako removeall(), to funguje jen u jednotlivých uzlů

Editace buněk Funguje podobně jako u seznamu Pokud je strom sestaven ze String, funguje automatická editace treeview.seteditable(true) treeview.setcellfactory(textfieldtreecell.fortreeview()) Pro primitivní datové typy se model sám aktualizuje Pro jiné objekty ve stromu je třeba použít vlastní TreeCell<T> Nastavit přes CellFactory Překrýt updateitem() zobrazení dat startedit() vytvoření editoru, obsluha ukončení editace (ENTER, ESC) canceledit() návrat do zobrazovacího režimu Nastavit obsluhu setoneditcommit() nebo ukládat data do modelu přímo v buňce (přes getitem())

Existující buňky Podobné jako u seznamu CheckBoxTreeCell ChoiceBoxTreeCell ComboBoxTreeCell TextFieldTreeCell Textové buňky mohou mít StringConverter<T> Nastaven jako parametr fortreeview() Výběrové buňky mohou mít ObservableList<T> Nastaven jako parametr fortreeview() Podobně jako u tabulky lze zjistit index (getindex(), je to potomek IndexedCell) Pořadí mezi aktuálně rozbalenými buňkami není stálý! Mění se i jestli je buňka odd nebo even

Naslouchání událostem Stačí poslouchat na kořeni stromu Je nežádoucí poslouchat na každém TreeItem TreeItem nemá seton metody Pro naslouchání addeventhandler(eventtype, EventHandler) Události: TreeItem.valueChangedEvent TreeItem.treeItemCountChangedEvent TreeItem.branchExpandedEvent() TreeItem.branchCollapsedEvent()

Vlastní CellFactory treeview.setcellfactory( new Callback<TreeView<String>, TreeCell<String>>(){ public TreeCell<String> call(treeview<string> p) { ); return new TextFieldTreeCellImpl(); Využívá rozhraní Callback<P, R> P typ parametru volané metody R typ návratové hodnoty treeview.setcellfactory(treev -> {return new TextFieldTreeCellImpl(); );

Porovnávání potomků Lze řadit potomky v jednom uzlu Potomci jsou v ObservableList(), ten má metodu sort(comparator) Parametr sort() může být null, pokud jsou prvky Comparable Bohužel TreeItem<Item> není Comparable a nedeleguje compareto() na svůj Item implementovat vlastní TreeItem jako potomka nebo napsat komparátor Pokud jsou Item porovnatelné, je to snadné parent.getchildren().sort((item1, item2) -> { return item1.getvalue().compareto(item2.getvalue()); );

Vlastní buňka TreeCell<T> class TextFieldTreeCellImpl extends TreeCell<String> { private TextField textfield; public void startedit() { super.startedit(); if (textfield == null) { createtextfield(); settext(null); setgraphic(textfield); textfield.selectall(); public void canceledit() { super.canceledit(); settext((string) getitem()); setgraphic(gettreeitem().getgraphic());

Vlastní buňka TreeCell<T> private void createtextfield() { textfield = new TextField(getString()); textfield.setonkeyreleased(new EventHandler<KeyEvent>() { public void handle(keyevent t) { if (t.getcode() == KeyCode.ENTER) { commitedit(textfield.gettext()); else if (t.getcode() == KeyCode.ESCAPE) { canceledit(); );

Vlastní buňka TreeCell<T> public void updateitem(string item, boolean empty) { super.updateitem(item, empty); if (empty) { settext(null); setgraphic(null); else { if (isediting()) { if (textfield!= null) { textfield.settext(getstring()); settext(null); setgraphic(textfield); else { settext(getstring()); setgraphic(gettreeitem().getgraphic());

Reakce na změnu výběru Hodí se při aktualizaci komponent s doplňující informací Výběr je kolekce ObservableList<T>, je třeba reagovat na změnu jejího obsahu Společné pro všechny komponenty umožňující výběr Dvě metody addlistener() nutné uvést typ parametru ancestortrv.getselectionmodel().getselecteditems(). addlistener((listchangelistener.change <? extends TreeItem<Ancestor>> change) -> { dosomething(); ); ListChangeListener.Change obsahuje informace o provedené změně (jaké prvky byly přidány)

Tabulka TreeTableView<S> Kombinace tabulkového a stromového zobrazení První sloupec se chová jako strom je možné v něm rozbalovat a sbalovat uzly musí fungovat jako klíč ke stromu Datový model je stejný jako u stromu Může obsahovat složitý objekt Jednotlivé vlastnosti mohou být ve sloupcích tabulky Lze vybírat celé řádky nebo jednotlivé buňky

Sloupce TreeTableColumn<S, T> Podobný jako sloupec tabulky S typ dat v řádku T typ dat ve sloupci Stejně jako u tabulky může mít podsloupce Stejně jako u tabulky funguje řazení podle sloupců Datový model není 1 kolekce data se řadí jen v rámci uzlů Řazení celého stromu lze omezit jen na prvky první úrovně

Data pro sloupec Nutné nastavit setcellvaluefactory(), jako u tabulky Pokud jsou v modelu beany (mají setry a getry), lze použít TreeItemPropertyValueFactory column.setcellvaluefactory( new TreeItemPropertyValueFactory<Employee, String>("property")); Pokud chci hodnotu určit sám, musím továrnu vytvořit Musí vracet data zabalená do ObservableItem<ColumnType> ReadOnlyStringWrapper, SimpleStringProperty, column.setcellvaluefactory( (TreeTableColumn.CellDataFeatures<Employee, String> param) -> { return new ReadOnlyStringWrapper (param.getvalue().getvalue().getemail()); );

Buňky Datový model sestaven z TreeItem<RowType> Stejná třída jako u TreeView Potomci musí být stejného typu trochu složitější vytvořit heterogenní strom Buňky jsou potomci TreeTableCell<RowType, CellType> Existují ekvivalenty všech buněk pro TableView Nové buňky a továrny na buňky lze vytvářet stejně jako u TableView (včetně zpracování obsluh při editaci) Při editaci nutné uložit změny do modelu empcolumn.setoneditcommit(event -> { event.gettreetableposition().gettreeitem(). getvalue(). setname(event.getnewvalue()); );

Heterogenní strom Nelze mít různé typy uzlů ve stromu má taková komponenta smysl? Lze vytvořit hierarchickou strukturu (např. oddělení a zaměstnanci) se stejným typem vyplním jen jméno (první sloupec) a ostatní data nechám prázdná Potřebuji zajistit aby byly prázdné i kolonky v cellvaluefactory upravím získání hodnoty když vrátí null, buňka nic nezobrazí (pozor na vlastní buňky) column.setcellvaluefactory(param -> { if (param.getvalue().getvalue().ishierarchy()) { return null; else return new ReadOnlyStringWrapper (param.getvalue().getvalue().getdata()); );

Vybraná data Lze nastavit mnohonásobný výběr treetableview.getselectionmodel(). setselectionmode(selectionmode.multiple); Přes getselecteditems() lze získat kolekci vybraných TreeItem<RowType> Lze povolit výběr jednotlivých buněk (funguje i u TableView) treetableview.getselectionmodel(). setcellselectionenabled(true); Metoda getselecteditems() opět vrací všechny vybrané řádky Metoda getselectedcells() vrací kolekci TreeTablePositions<RowType, CellType> ze které jde získat číslo řádku a sloupce buňky a TreeItem<RowType> z příslušného řádku

Děkuji za pozornost OTÁZKY? NÁZORY, PŘIPOMÍNKY? PŘÍŠTĚ: FXML, CSS, TOK UDÁLOSTÍ V APLIKACI