Lekce 5 - Práce s CSV soubory v Kotlin - Načtení objektů
V minulé lekci, Práce s CSV soubory v Kotlin - Uložení objektů, jsme si vytvořili formulářovou aplikaci s databází uživatelů, která ukládá instance do textových souborů ve formátu CSV.
V dnešním Kotlin tutoriálu implementujeme do naší objektové formulářové aplikace načtení uživatelů z textového souboru ve formátu CSV.
Doplnění třídy Databaze
Do třídy Databaze
si nejprve přidáme metodu pro načtení
uživatelů.
Metoda nacti()
Kód metody je následující:
@Throws(IOException::class) fun nacti() { // Nejprve vyprázdníme uzivatele. uzivatele.clear() // Pak projdeme všechny řádky v souboru, každý rozsekáme na části podle středníků, // rozdělené části pak použijeme pro přidání nového uživatele. for (radek in Files.readAllLines(soubor)) { val rozdeleno = radek.split(";".toRegex()).toTypedArray() pridejUzivatele(rozdeleno[0], rozdeleno[1].toInt(), LocalDate.parse(rozdeleno[2])) } }
Na začátku metody kolekci uzivatele
vyprázdníme zavoláním
metody clear()
. Soubor soubor
budeme číst řádek po
řádku v cyklu. Každý řádek rozdělíme metodou split()
,
které předáme oddělovač ;
. Následně do kolekce
uzivatele
, pomocí metody pridejUzivatele()
, přidáme
objekt s rozdělenými hodnotami.
Prezentační vrstva aplikace
Nyní se pustíme do úpravy našeho formuláře. Do něj si připravíme nové formulářové prvky. Budeme chtít docílit následujícího vzhledu:
Otevřeme si formular.fxml
ve Scene Builderu a do našeho
kontejneru VBox
vložíme další dva kontejnery typu
Pane
. První bude obsahovat dva popisky Label
, kterým
vyplníme text dle ukázky. Textu Databáze uživatelů
zvětšíme
písmo a nastavíme tučný font v záložce Properties.
Druhý Pane
kontejner bude obsahovat tři vložené kontejnery.
Jako první přidáme ScrollPane
, ve kterém budeme zobrazovat
seznam uživatelů typu ListView
. Poté doplníme další
Pane
kontejner pro zobrazovaní detailu
uživatele. Ten bude obsahovat sedm Label
popisků -
nadpis a popisek pro jméno, věk a datum registrace, vždy s odpovídajícím
prázdným polem pro načtení detailu. Pod kontejner vložíme naše tlačítko
Uložit a doplníme tlačítko pro načtení databáze.
Nakonec přidáme poslední Pane
, který bude opět obsahovat
popisky pro nadpis a údaje o uživateli, jehož chceme do databáze přidat.
Pro odpovídající prázdná pole ale tentokrát zvolíme
TextField
pro zadání jména, Spinner
pro výběr
věku a DatePicker
, který nám usnadní zadání data registrace.
Pod kontejner nezapomeneme doplnit další tlačítko Přidat.
Doplnění obsluhy formuláře
Upravený formulář uložíme a v IntelliJ si otevřeme náš kontroler.
Deklarace FXML proměnných
V kontroleru nejprve deklarujeme nové proměnné pro seznam uživatelů a jednotlivé položky pro přidání uživatele a zobrazení jeho detailu:
class DatabazeKontroler : Initializable { var databaze: Databaze? = null @FXML private lateinit var novyUzivatelVek: Spinner<Int> @FXML private lateinit var novyUzivatelJmeno: TextField @FXML private lateinit var novyUzivatelDatumRegistrace: DatePicker @FXML private lateinit var detailUzivatelJmenoLabel: Label @FXML private lateinit var detailUzivatelVekLabel: Label @FXML private lateinit var detailUzivatelDatumLabel: Label @FXML private var uzivateleList: ListView<Uzivatel> = ListView<Uzivatel>() ... }
Uvedené proměnné nyní můžeme nastavit ve Scene Builderu patřičným
komponentám v záložce Code jako fx:id
.
Přepis metody initialize()
V kontroleru máme od minule hotový konstruktor, který měnit nebudeme.
Budeme muset ale přepsat metodu initialize()
, v níž zprovozníme
náš Spinner
a nastavíme zobrazování detailu vybraného
uživatele:
override fun initialize(p0: URL?, p1: ResourceBundle?) { /** * Vytvoření ActionListener pro Spinner */ val spinnerValueFactory = SpinnerValueFactory.IntegerSpinnerValueFactory(1, 100) // Vytvoření rozsahu hodnot pro Spinner spinnerValueFactory.value = 18 // Nastavení defaultní hodnoty novyUzivatelVek.valueFactory = spinnerValueFactory // Registrace SpinnerValueFactory pro Spinner // Vytvoření ActionListener pro ListView uzivateleList, při kliknutí na položku se zobrazí detaily uživatele uzivateleList.selectionModel.selectedItemProperty().addListener { _ -> val vybranyUzivatel = uzivateleList.selectionModel.selectedItem // Získání vybraného prvku v ListView if (vybranyUzivatel != null) { detailUzivatelJmenoLabel.text = vybranyUzivatel.jmeno // Vypsání jména uživatele detailUzivatelVekLabel.text = vybranyUzivatel.vek.toString() // Vypsání věku uživatele detailUzivatelDatumLabel.text = vybranyUzivatel.datumRegistrace.toString() // Vypsání datum registrace uživatele } } }
V první části nastavujeme pro Spinner
věkové rozmezí a
defaultní zobrazení hodnoty 18
. Dále přidáváme
ActionListener
, díky němuž získáme a vypíšeme jméno, věk a
datum registrace uživatele.
Kód jsme opodmínkovali pro případ, že by nebyl žádný uživatel vybrán (list by byl prázdný).
Obsluha tlačítek
Nyní nám zbývá doplnit obsluhu našich tlačítek.
Metoda ulozData()
Tlačítko Uložit máme připravené z dřívějška. V Scene
Builder, v záložce Code voláme v políčku On Action metodu
ulozData()
. Z ní odstraníme vytvoření testovacích uživatelů
a ponecháme jen volání metody uloz()
ze třídy
Databaze
v try-catch
bloku. Metoda bude tedy vypadat
takto:
@FXML private fun ulozData() { try { databaze!!.uloz() } catch (e: IOException) { println("ERROR: Databázi se nepodařilo uložit, zkontrolujte přístupová práva k souboru.") println(e.message) } }
Metoda nacistData()
Obdobně ve Scene Builderu zaregistrujeme metodu nacistData()
u
tlačítka Načíst. V kontroleru si metodu doplníme:
@FXML private fun nacistData() { try { uzivateleList.items.clear() databaze!!.nacti() for (u in databaze!!.vratVsechny()) { uzivateleList.items.add(0, u) // Přidání nového záznamu Uživatele do ListView } } catch (e: IOException) { println("ERROR: Databázi se nepodařilo načíst, soubor zřejmě neexistuje.") println(e.message) } }
Nejprve vyprázdníme stávající seznam uzivateleList
, poté
zavoláme metodu nacti()
. V cyklu nakonec metody
vratVsechny()
získáme seznam uživatelů, které postupně
přidáváme do vyprázdněné kolekce v kontejneru ScrollPane
.
V reálné aplikaci by se načtení vykonalo asi automaticky po spuštění aplikace a uložení po ukončení. Pro názornost si to však ponecháme na tlačítkách.
Metoda vytvoritUzivatele()
Poslední zprovozníme tlačítko pro přidání nového uživatele:
@FXML private fun vytvoritUzivatele() { try { val jmeno: String = novyUzivatelJmeno.text // Získání hodnoty z TextField novyUzivatelJmeno val vek: Int = novyUzivatelVek.value // Získání hodnoty ze Spinner novyUzivatelVek /** * Nejdříve získáme hodnotu z DatePicker novyUzivatelDatumRegistrace, * Poté získáme den, měsíc a rok. Nakonec vytvoříme datum ve formátu "den'.'Měsíc'.'Rok" */ val datePickerValue = novyUzivatelDatumRegistrace.value val den = datePickerValue.dayOfMonth.toString() val mesic = datePickerValue.monthValue.toString() val rok = datePickerValue.year.toString() val datum = "${den}.${mesic}.${rok}" val registrovan: LocalDate = LocalDate.parse(datum, DateTimeFormatter.ofPattern("d'.'M'.'y")) databaze!!.pridejUzivatele(jmeno, vek, registrovan) // Přidání nového záznamu do databáze val uzivatel = Uzivatel(jmeno, vek, registrovan) uzivateleList.items.add(0, uzivatel) // Přidání nového záznamu Uživatele do ListView } catch (e: IOException) { println(e.message) } }
V té nejdříve získáváme hodnoty položek TextField
,
Spinner
a DatePicker
, datum musíme naformátovat.
Nakonec přidáme uživatele do databáze a získanými údaji doplníme také
náš seznam uzivateleList
.
Testování
Zkusíme aplikaci spustit, načíst uložená data, přidat nového uživatele a vše opět uložit:
Podobně bychom si mohli napsat i mazání uživatelů.
V následujícím cvičení, Řešené úlohy k 1.-5. lekci práce se soubory v Kotlin, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 3x (41.23 kB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin