Obsah
1. Tvorba grafického uživatelského rozhraní v Pythonu: dokončení popisu widgetů v knihovně appJar
2. Horizontální posuvník (slider, scale)
3. Zobrazení hodnot na horizontální ose posuvníku
4. Zobrazení aktuálně vybrané hodnoty na posuvníku
5. Změna rozsahu hodnot, které lze posuvníkem vybrat
7. Callback funkce volaná při změně posuvníku
8. Widget zobrazující průběh činnosti (meter)
9. Změna hodnoty widgetu meter
10. Úprava barevného gradientu widgetu meter
11. Automatické sledování a zobrazení hodnot vybrané proměnné
12. Widget meter rozdělený na dva barevné gradienty
13. Úprava obou barevných gradientů rozděleného widgetu meter
14. Widget umožňující současné zobrazení dvou hodnot (dual meter)
16. Použití aktuálního data popř. explicitní určení odlišného data
17. Widget umožňující uchopení a přesun okna
18. Horizontální a vertikální oddělovač widgetů
19. Repositář s demonstračními příklady
1. Tvorba grafického uživatelského rozhraní v Pythonu: dokončení popisu widgetů v knihovně appJar
V již třetím pokračování článku o tvorbě grafického uživatelského rozhraní v Pythonu s využitím knihovny appJar dokončíme popis většiny zbývajících ovládacích prvků (widgetů), z nichž je možné skládat složitější dialogy a formuláře (widgety pro vstup testu si popíšeme společně s formuláři). Pro připomenutí jsou v následující tabulce vypsány všechny základní widgety, které tato knihovna podporuje. Odkazy vedou na podrobnější popis každého widgetu:
Jméno widgetu | Stručný popis |
---|---|
Label | textové návěští neměnitelné uživatelem |
Message | několikařádkové textové návěští (viz Label) |
Entry | šest typů vstupních polí (základní + 5 speciálních) |
TextArea | několikařádkové vstupní pole |
Button | klasické „klikací“ tlačítko, existují však i další varianty (tlačítko s ikonou atd.) |
RadioButton | přepínací tlačítko, které je typicky sdružováno do větších skupin |
CheckBox | zaškrtávací tlačítko |
Properties | skupina zaškrtávacích tlačítek |
OptionBox | výběrové pole se seznamem voleb (drop-down box) |
SpinBox | výběrové pole s přetáčením voleb |
ListBox | seznam prvků s možností výběru jednoho prvku či skupiny prvků |
Scale | scrollovací prvek (horizontální a vertikální posuvník) |
DatePicker | výběr data |
Link | klikací odkaz |
WebLink | klikací odkaz |
Grip | ploška sloužící k přesunu okna/dialogu/toolbaru |
Meter | (pasivní) zobrazení průběhu výpočtu atd. |
Separator | (pasivní) horizontální či vertikální oddělení widgetů |
2. Horizontální posuvník (slider, scale)
Prvním widgetem, který si dnes popíšeme, je horizontální posuvník. Většinou se tento ovládací prvek nazývá slider, ovšem v knihovně appJar zvolili název scale. Tento posuvník se v nejjednodušším případě vytváří metodou addScale popř. metodou addLabelScale. Druhá z těchto metod navíc zobrazí na levé straně widgetu i jeho název:
app.addScale("scale1") app.addLabelScale("scale1")
Pro čtení aktuálně nastavené pozice posuvníku použijte metodu getScale:
value1 = app.getScale("scale1") value2 = app.getScale("scale2")
Obrázek 1: Nejjednodušší forma horizontálního posuvníku, který implicitně umožňuje vybírat hodnoty od 1 do 100 (včetně obou mezí).
V dnešním prvním demonstračním příkladu se zobrazí jeden posuvník a jeho hodnota je vypsána do informačního dialogu po stisku tlačítka „Show scale value“:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addLabelScale("scale") app.addButton("Show scale value", onButtonPress) app.addButton("Quit", onButtonPress) app.go()
Obrázek 2: Zobrazení aktuálně vybrané hodnoty na posuvníku.
3. Zobrazení hodnot na horizontální ose posuvníku
Posuvník z prvního příkladu ve skutečnosti nebyl nakonfigurován tak, aby byl uživatelsky přívětivý, protože nebylo zřejmé, jaký rozsah hodnot vlastně posuvník představuje. Tento problém lze velice snadno napravit, protože pod posuvníkem může být zobrazena osa s hodnotami. Tato osa se zapíná metodou showScaleValue, které se kromě jména posuvníku předá i interval mezi zobrazenými hodnotami. Musíte si pouze dát pozor na to, aby nebylo hodnot zobrazeno příliš mnoho, protože by se překrývaly (knihovna appJar tuto kontrolu za nás neudělá):
app.showScaleIntervals("scale", 20)
Obrázek 3: Posuvník, pod nímž je zobrazena osa s hodnotami.
V následujícím demonstračním příkladu je zajištěno, že se pod posuvníkem zobrazí i osa s hodnotami:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 20) app.addButton("Show scale value", onButtonPress, 1, 0) app.addButton("Quit", onButtonPress, 1, 1) app.go()
4. Zobrazení aktuálně vybrané hodnoty na posuvníku
Uživatelskou přívětivost při použití posuvníku lze dále vylepšit tak, že nad jeho posuvnou částí zobrazíme aktuálně nastavenou hodnotu. Tato konfigurace je velmi snadná, protože pouze postačuje zavolat následující metodu, které se pouze předá jméno posuvníku:
app.showScaleValue("scale")
Alternativně lze použít i volání:
app.showScaleValue("scale", show=True)
Opětovný zákaz zobrazení aktuální hodnoty se provede voláním:
app.showScaleValue("scale", show=False)
Obrázek 4: Posuvník, nad nímž je zobrazena aktuálně vybraná hodnota. Současně se pod posuvníkem zobrazuje osa s hodnotami. Jedná se o největší množství informací, které tento widget dokáže v dané chvíli poskytnout.
Podívejme se nyní na demonstrační příklad, v němž je zobrazen posuvník jak s osou hodnot, tak i s aktuálně vybranou hodnotou:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 20) app.showScaleValue("scale") app.addButton("Show scale value", onButtonPress, 1, 0) app.addButton("Quit", onButtonPress, 1, 1) app.go()
5. Změna rozsahu hodnot, které lze posuvníkem vybrat
Ve druhé kapitole jsme si řekli, že posuvníkem je možné vybírat hodnoty z rozsahu 1 až 100. Samozřejmě se nejedná o jediný možný rozsah, který by bylo nutné programově přepočítávat na rozsah požadovaný zpracovávanou úlohou. Pomocí metody setScaleRange je totiž možné specifikovat vlastní dolní i horní mez hodnot vrácených posuvníkem (ovšem na obrazovce se posuvník vždy bude pohybovat od levého dorazu do dorazu pravého):
app.setScaleRange("scale", dolní_mez, horní_mez)
popř. je možné nastavit aktuální hodnotu:
app.setScaleRange("scale", dolní_mez, horní_mez, aktuální_hodnota)
Obrázek 5: Posuvník umožňující vybírat hodnoty z rozsahu 50 až 150 (včetně obou mezí).
Opět si ukažme demonstrační příklad, v němž nakonfigurujeme možnosti posuvníku:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleRange("scale", 50, 150, 100) app.addButton("Show scale value", onButtonPress, 1, 0) app.addButton("Quit", onButtonPress, 1, 1) app.go()
6. Vertikální posuvník
Metodou setScaleVertical lze vytvořit vertikální posuvník, který je zobrazen na šestém obrázku. Při použití vertikálního posuvníku si musíte dát pozor na to, aby se zbytečně „nenatáhly“ ostatní widgety umístěné vedle posuvníku popř. aby nebyl posuvník příliš nízký. Řešení poskytuje metoda setPadding a roztažení posuvníku přes několik řádků:
app.setScaleVertical("scale")
Obrázek 6: Vertikální posuvník zobrazený na dialogu.
Další příklad po svém spuštění zobrazí vertikální posuvník umístěný v levé části dialogu. Posuvník zabere všechny tři řádky pomyslné mřížky:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) app = gui() app.setSticky("news") app.setPadding(10, 10) app.addLabelScale("scale", rowspan=3) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleRange("scale", 50, 150, 100) app.setScaleVertical("scale") app.addButton("Show scale value", onButtonPress, 0, 1) app.addLabel("", "", 1, 1) app.addButton("Quit", onButtonPress, 2, 1) app.go()
7. Callback funkce volaná při změně posuvníku
Ve chvíli, kdy uživatel změní pozici posuvníku, může dojít k automatickému zavolání callback funkce, které se v jediném parametru předá jméno widgetu (posuvníku), kterého se tato událost týká. Registraci takové callback funkce provedeme velmi snadno:
app.setScaleChangeFunction(jméno_posuvníku, scaleCallback)
Samotná callback funkce může vypadat například takto:
def scaleCallback(widgetName): value = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=value))
Obrázek 7: Po změně pozice posuvníku se automaticky změní titulek okna.
Podívejme se nyní na demonstrační příklad, který dokáže změnit titulek okna po změně pozice posuvníku:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): value = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=value)) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleChangeFunction("scale", scaleCallback) app.setScaleRange("scale", 50, 150, 100) app.addButton("Show scale value", onButtonPress, 1, 0) app.addButton("Quit", onButtonPress, 1, 1) app.go()
8. Widget zobrazující průběh činnosti (meter)
Většina ovládacích prvků, s nimiž jsme se doposud seznámili, dokáže aktivně reagovat na akce prováděné uživatelem (klik, drag and drop atd.). Ovšem widget nazvaný meter je vlastně z tohoto pohledu pasivní, protože nijak nereaguje na přímé uživatelovy akce. Tento ovládací prvek je totiž určený na zobrazení průběhu nějaké činnosti, takže se v jiných grafických knihovnách jmenuje progress bar apod. (ostatně i z tohoto důvodu jsou hodnoty zobrazené v rozsahu 0% až 100%). V knihovně appJar se widget meter v tom nejjednodušším případě vytváří takto:
app.addMeter("progressBar")
popř. s udáním pozice prvku v rámci neviditelné mřížky (grid):
app.addMeter("progressBar", 2, 3)
Obrázek 8: Nejjednodušší podoba widgetu, který umožňuje zobrazit průběh nějaké činnosti. Povšimněte si, že tento widget zobrazuje hodnoty v procentech.
Podívejme se nyní na způsob přidání tohoto widgetu do našeho demonstračního příkladu. Je to velmi snadné:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() app = gui() app.setSticky("news") app.setPadding(10, 2) app.addMeter("progressBar", 1, 0) app.addButton("Quit", onButtonPress, 1, 1) app.go()
9. Změna hodnoty widgetu meter
Widget typu meter můžeme použít dvěma způsoby:
- Hodnotu zobrazenou tímto widgetem (0% až 100%) budeme nastavovat explicitně v programu. V tomto případě se použije metodaapp.setMeter().
- Necháme widget, aby sám sledoval zvolenou proměnnou a aktualizoval svoji hodnotu automaticky. Aby vše fungovalo, musíme zaregistrovat událost pomocíapp.registerEvent(vhodná_callback_funkce).
Nejdříve si ukážeme první způsob, tj. explicitní nastavení hodnoty zobrazované widgetem. Hodnotu budeme získávat z posuvníku:
def scaleCallback(widgetName): value = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=value)) app.setMeter("progressBar", value)
Obrázek 9: Nastavení hodnoty widgetu meter na 42%
Úplný zdrojový kód příkladu vypadá následovně:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): value = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=value)) app.setMeter("progressBar", value) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addMeter("progressBar", 0, 0, colspan=2) app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleChangeFunction("scale", scaleCallback) app.setScaleRange("scale", 0, 100, 50) app.addButton("Show scale value", onButtonPress, 2, 0) app.addButton("Quit", onButtonPress, 2, 1) app.go()
10. Úprava barevného gradientu widgetu meter
V případě, že vám nevyhovuje výchozí barevný gradient použitý ve widgetu meter, není žádný problém ho změnit. Použijte přitom metodu nazvanou setMeterFill, které se ve druhém parametru předá barva ve formě řetězce:
app.setMeterFill("progressBar", "green")
popř. je možné barvu specifikovat i „hexa-trojicí“ používanou i v HTML a CSS:
app.setMeterFill("progressBar", "#aabbcc")
Obrázek 10: Výchozí barevný gradient widgetu meter.
Obrázek 11: Změna gradientu na škálu zeleného odstínu.
Opět si ukažme zařazení výše uvedeného kódu do demonstračního příkladu:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): value = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=value)) app.setMeter("progressBar", value) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addMeter("progressBar", 0, 0, colspan=2) app.setMeterFill("progressBar", "green") app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleChangeFunction("scale", scaleCallback) app.setScaleRange("scale", 0, 100, 50) app.addButton("Show scale value", onButtonPress, 2, 0) app.addButton("Quit", onButtonPress, 2, 1) app.go()
11. Automatické sledování a zobrazení hodnot vybrané proměnné
Ovládací prvek meter dokáže automaticky sledovat a zobrazit hodnotu vybrané proměnné (ideálně ve chvíli, kdy tato hodnota leží v rozsahu 0 až 100). Aby toto sledování pracovalo korektně, je nutné vytvořit „univerzální“ callback funkci zavolanou ve chvíli, kdy je nutné změnit hodnoty zobrazené v GUI. V této callback funkci přečteme proměnnou meterValue (což je jen příklad) a změníme hodnotu zobrazovanou widgetem meter:
def updateMeter(): app.setMeter("progressBar", meterValue)
Tuto univerzální callback funkci dále zaregistrujeme:
app.registerEvent(updateMeter)
Pokud si spustíte další demonstrační příklad, můžete posuvníkem měnit hodnotu zobrazenou widgetem meter. Povšimněte si zpoždění mezi změnou posuvníku a zobrazením hodnoty. Toto zpoždění je způsobeno tím, že se callback funkce nevolá příliš často:
#!/usr/bin/env python from appJar import gui meterValue = 50 def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): global meterValue meterValue = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=meterValue)) def updateMeter(): app.setMeter("progressBar", meterValue) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addMeter("progressBar", 0, 0, colspan=2) app.setMeterFill("progressBar", "green") app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleChangeFunction("scale", scaleCallback) app.setScaleRange("scale", 0, 100, meterValue) app.registerEvent(updateMeter) app.addButton("Show scale value", onButtonPress, 2, 0) app.addButton("Quit", onButtonPress, 2, 1) app.go()
12. Widget meter rozdělený na dva barevné gradienty
Pokud ovládací prvek meter vytvoříme metodou addSplitMeter:
app.addSplitMeter("progressBar")
a nikoli metodou addMeter:
app.addMeter("progressBar")
bude tento widget zobrazený takovým způsobem, jaký je naznačený na dalším screenshotu:
Obrázek 12: Widget meter rozdělený na dva barevné gradienty.
Funkce tohoto widgetu však zůstane zachována, o čemž se můžeme snadno přesvědčit spuštěním dalšího příkladu:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): value = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=value)) app.setMeter("progressBar", value) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addSplitMeter("progressBar", 0, 0, colspan=2) app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleChangeFunction("scale", scaleCallback) app.setScaleRange("scale", 0, 100, 50) app.addButton("Show scale value", onButtonPress, 2, 0) app.addButton("Quit", onButtonPress, 2, 1) app.go()
13. Úprava obou barevných gradientů rozděleného widgetu meter
Ve chvíli, kdy použijeme widget meter rozdělený na dva barevné gradienty, již není možné barvu tohoto ovládacího prvku nastavit způsobem, který jsme si popsali v desáté kapitole, tj. voláním:
app.setMeterFill("progressBar", "green")
Namísto toho je nutné předat metodě setMeterFill dvě barvy, a to s využitím n-tice nebo seznamu:
app.setMeterFill("progressBar", ["green", "yellow"])
Obrázek 13: Explicitní nastavení dvou barevných gradientů.
Úprava zdrojového kódu příkladu je v tomto případě triviální:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scale: {s}".format(s=app.getScale("scale")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): value = app.getScale(widgetName) app.setTitle("Scale: {v}".format(v=value)) app.setMeter("progressBar", value) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addSplitMeter("progressBar", 0, 0, colspan=2) app.setMeterFill("progressBar", ["green", "yellow"]) app.addLabelScale("scale", colspan=2) app.showScaleIntervals("scale", 25) app.showScaleValue("scale") app.setScaleChangeFunction("scale", scaleCallback) app.setScaleRange("scale", 0, 100, 50) app.addButton("Show scale value", onButtonPress, 2, 0) app.addButton("Quit", onButtonPress, 2, 1) app.go()
14. Widget umožňující současné zobrazení dvou hodnot (dual meter)
Další varianta widgetu meter spočívá v tom, že tento widget zobrazí dvě na sobě nezávislé hodnoty. Nejdříve se podívejme na screenshot, z něhož je patrné, jak takové zobrazení vypadá:
Obrázek 14: Widget meter zobrazující dvě hodnoty, jednu nalevo a druhou napravo od společného počátku.
Tuto variantu widgetu vytvoříme následovně:
app.addDualMeter("progressBar", 0, 0, colspan=2)
Nastavíme barvu obou částí:
app.setMeterFill("progressBar", ["yellow", "red"])
A pozici (hodnoty) obou částí, opět s využitím n-tice nebo seznamu:
def scaleCallback(widgetName): value1 = app.getScale("scale1") value2 = app.getScale("scale2") app.setMeter("progressBar", [value1, value2])
Následuje zdrojový kód příkladu, v němž je takto upravený widget použit:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scales:\n{s1}\n{s2}".format( s1=app.getScale("scale1"), s2=app.getScale("scale2")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): value1 = app.getScale("scale1") value2 = app.getScale("scale2") app.setMeter("progressBar", [value1, value2]) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addDualMeter("progressBar", 0, 0, colspan=2) app.setMeterFill("progressBar", ["yellow", "red"]) app.addLabelScale("scale1", colspan=2) app.showScaleIntervals("scale1", 25) app.showScaleValue("scale1") app.addLabelScale("scale2", colspan=2) app.showScaleIntervals("scale2", 25) app.showScaleValue("scale2") app.setScaleChangeFunction("scale1", scaleCallback) app.setScaleChangeFunction("scale2", scaleCallback) app.setScaleRange("scale1", 0, 100, 50) app.setScaleRange("scale2", 0, 100, 50) app.addButton("Show scale value", onButtonPress, 3, 0) app.addButton("Quit", onButtonPress, 3, 1) app.go()
15. Widget pro výběr data
Další widget, s nímž se dnes seznámíme, vlastně spojuje tři listboxy určené pro výběr data. Nejedná se tedy o plnohodnotný kalendář (což je zajisté škoda), ovšem i přesto může mít tento ovládací prvek své využití, protože automaticky hlídá počet dnů v měsíci, a to i pro přestupné roky. Podívejme se nejdříve na to, jak je tento widget zobrazen na Linuxu:
Obrázek 15: Widget pro výběr data se skládá ze tří listboxů (a nevypadá tedy příliš uživatelsky přívětivě).
Tento widget se vytvoří voláním:
app.addDatePicker("datePicker")
Pro jistotu ještě přidejte předpokládaný rozsah roků, které bude možné vybrat:
app.setDatePickerRange("datePicker", 2000, 2017)
Vybrané datum se získá voláním:
getDatePicker("datePicker")
Podívejme se nyní na příklad, v němž je tento widget použitý:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() def showDate(btn): msg = "Selected date: {d}".format(d=app.getDatePicker("datePicker")) app.infoBox("Show scale:", msg) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addDatePicker("datePicker") app.setDatePickerRange("datePicker", 2000, 2017) app.addButton("Show selected date", showDate, 2, 0) app.addButton("Quit", onButtonPress, 2, 1) app.go()
Obrázek 16: Zobrazení vybraného data.
16. Použití aktuálního data popř. explicitní určení odlišného data
Widget date picker je možné „donutit“ k zobrazení aktuálního data po zavolání metody setDatePicker, které se předá pouze jméno widgetu a žádný další parametr:
app.setDatePicker("datePicker")
Pokud naopak potřebujete vybrat jiné explicitně zadané datum, použijte volání:
setDatePicker(title, date="yyyy-mm-dd)
Obrázek 17: Nastavení aktuálního data (ve chvíli přípravy článku).
Podívejme se nyní na příklad, jenž po svém spuštění zobrazí aktuální datum:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() def showDate(btn): msg = "Selected date: {d}".format(d=app.getDatePicker("datePicker")) app.infoBox("Show scale:", msg) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addDatePicker("datePicker") app.setDatePickerRange("datePicker", 2000, 2018) # toto volani musi byt umisteno za predchozi prikaz! app.setDatePicker("datePicker") app.addButton("Show selected date", showDate, 2, 0) app.addButton("Quit", onButtonPress, 2, 1) app.go()
17. Widget umožňující uchopení a přesun okna
Předposlední widget, který si dnes popíšeme, umožňuje uchopení a přesun okna; není tedy nutné používat část okna s titulkem. Tento widget se vytvoří velmi jednoduše:
app.addGrip()
Obrázek 18: Widget umožňující uchopení a přesun okna.
Chování tohoto widgetu si můžeme sami jednoduše odzkoušet, ovšem jeho reálné použití může být problematické, protože tento ovládací prvek uživatelé pravděpodobně nebudou znát:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() app = gui() app.setSticky("news") app.setPadding(10, 2) app.addLabel("topLabel", "\u25bc", 0, 1) app.addLabel("leftLabel", "grip \u25b6", 1, 0) app.addLabel("rightLabel", "\u25c0 grip", 1, 2) app.addLabel("bottomLabel", "\u25b2", 2, 1) app.addGrip(1, 1) app.addButton("Quit", onButtonPress, 4, 1) app.go()
18. Horizontální a vertikální oddělovač widgetů
Do dialogů lze vložit horizontální a vertikální oddělovače, což je ostatně patrné při pohledu na další screenshot:
Obrázek 18: Horizontální a vertikální oddělovače widgetů.
Tyto oddělovače se vytváří metodami:
app.addHorizontalSeparator(y, x, colspan=2, colour="blue") app.addVerticalSeparator(y, x, rowspan=6)
Z příkladů volání je patrné, že se oddělovače pozicují stejně, jako všechny ostatní widgety:
#!/usr/bin/env python from appJar import gui def onButtonPress(buttonName): if buttonName == "Quit": app.stop() else: msg = "Your choice of scales:\n{s1}\n{s2}".format( s1=app.getScale("scale1"), s2=app.getScale("scale2")) app.infoBox("Show scale:", msg) def scaleCallback(widgetName): value1 = app.getScale("scale1") value2 = app.getScale("scale2") app.setMeter("progressBar", [value1, value2]) app = gui() app.setSticky("news") app.setPadding(10, 2) app.addDualMeter("progressBar", 0, 1, colspan=2) app.setMeterFill("progressBar", ["yellow", "red"]) app.addHorizontalSeparator(1, 1, colspan=2, colour="blue") app.addVerticalSeparator(0, 0, rowspan=6) app.addVerticalSeparator(0, 3, rowspan=6) app.addLabelScale("scale1", 2, 1, colspan=2) app.showScaleIntervals("scale1", 25) app.showScaleValue("scale1") app.addLabelScale("scale2", 3, 1, colspan=2) app.showScaleIntervals("scale2", 25) app.showScaleValue("scale2") app.addHorizontalSeparator(4, 1, colspan=2, colour="green") app.setScaleChangeFunction("scale1", scaleCallback) app.setScaleChangeFunction("scale2", scaleCallback) app.setScaleRange("scale1", 0, 100, 50) app.setScaleRange("scale2", 0, 100, 50) app.addButton("Show scale value", onButtonPress, 5, 1) app.addButton("Quit", onButtonPress, 5, 2) app.go()
19. Repositář s demonstračními příklady
Zdrojové kódy všech sedmnácti dnes popsaných demonstračních příkladů naleznete pod následujícími odkazy:
Poznámka: pro úspěšné spuštění těchto příkladů musíte mít v aktuálním adresáři rozbalenou knihovnu appJar!. Podrobnosti jsme si řekli v úvodním článku.
20. Odkazy na Internetu
- Hra Breakout napísaná v Tkinteri
https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/ - Hra Snake naprogramovaná v Pythone s pomocou Tkinter
https://www.root.cz/clanky/hra-snake-naprogramovana-v-pythone-s-pomocou-tkinter/ - TkDND
http://freecode.com/projects/tkdnd - Python Tkinter Fonts
https://www.tutorialspoint.com/python/tk_fonts.htm - The Tkinter Canvas Widget
http://effbot.org/tkinterbook/canvas.htm - Ovládací prvek (Wikipedia)
https://cs.wikipedia.org/wiki/Ovl%C3%A1dac%C3%AD_prvek_%28po%C4%8D%C3%ADta%C4%8D%29 - Rezervovaná klíčová slova v Pythonu
https://docs.python.org/3/reference/lexical_analysis.html#keywords - TkDocs: Styles and Themes
http://www.tkdocs.com/tutorial/styles.html - Drawing in Tkinter
http://zetcode.com/gui/tkinter/drawing/ - Changing ttk widget text color (StackOverflow)
https://stackoverflow.com/questions/16240477/changing-ttk-widget-text-color - The Hitchhiker's Guide to Pyhton: GUI Applications
http://docs.python-guide.org/en/latest/scenarios/gui/ - 7 Top Python GUI Frameworks for 2017
http://insights.dice.com/2014/11/26/5-top-python-guis-for-2015/ - GUI Programming in Python
https://wiki.python.org/moin/GuiProgramming - Cameron Laird's personal notes on Python GUIs
http://phaseit.net/claird/comp.lang.python/python_GUI.html - Python GUI development
http://pythoncentral.io/introduction-python-gui-development/ - Graphic User Interface FAQ
https://docs.python.org/2/faq/gui.html#graphic-user-interface-faq - TkInter
https://wiki.python.org/moin/TkInter - Tkinter 8.5 reference: a GUI for Python
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html - TkInter (Wikipedia)
https://en.wikipedia.org/wiki/Tkinter - appJar
http://appjar.info/ - appJar (Wikipedia)
https://en.wikipedia.org/wiki/AppJar - appJar na Pythonhosted
http://pythonhosted.org/appJar/ - appJar widgets
http://appjar.info/pythonWidgets/ - Stránky projektu PyGTK
http://www.pygtk.org/ - PyGTK (Wikipedia)
https://cs.wikipedia.org/wiki/PyGTK - Stránky projektu PyGObject
https://wiki.gnome.org/Projects/PyGObject - Stránky projektu Kivy
https://kivy.org/#home - Stránky projektu PyQt
https://riverbankcomputing.com/software/pyqt/intro - PyQt (Wikipedia)
https://cs.wikipedia.org/wiki/PyGTK - Stránky projektu PySide
https://wiki.qt.io/PySide - PySide (Wikipedia)
https://en.wikipedia.org/wiki/PySide - Stránky projektu Kivy
https://kivy.org/#home - Kivy (framework, Wikipedia)
https://en.wikipedia.org/wiki/Kivy_(framework) - QML Applications
http://doc.qt.io/qt-5/qmlapplications.html - KDE
https://www.kde.org/ - Qt
https://www.qt.io/ - GNOME
https://en.wikipedia.org/wiki/GNOME - Category:Software that uses PyGTK
https://en.wikipedia.org/wiki/Category:Software_that_uses_PyGTK - Category:Software that uses PyGObject
https://en.wikipedia.org/wiki/Category:Software_that_uses_PyGObject - Category:Software that uses wxWidgets
https://en.wikipedia.org/wiki/Category:Software_that_uses_wxWidgets - GIO
https://developer.gnome.org/gio/stable/ - GStreamer
https://gstreamer.freedesktop.org/ - GStreamer (Wikipedia)
https://en.wikipedia.org/wiki/GStreamer - Wax Gui Toolkit
https://wiki.python.org/moin/Wax - Python Imaging Library (PIL)
http://infohost.nmt.edu/tcc/help/pubs/pil/ - Why Pyjamas Isn’t a Good Framework for Web Apps (blogpost z roku 2012)
http://blog.pyjeon.com/2012/07/29/why-pyjamas-isnt-a-good-framework-for-web-apps/