Tvorba grafického uživatelského rozhraní v Pythonu s využitím knihovny PySimpleGUI

26. 12. 2023
Doba čtení: 23 minut

Sdílet

 Autor: Depositphotos
Pro tvorbu aplikací s grafickým uživatelským rozhraním v Pythonu máme na výběr množství knihoven a GUI toolkitů. Souběžně s vývojem toolkitů určených pro desktopy vznikají knihovny, zaměřené na rychlou tvorbu GUI.

Obsah

1. Tvorba grafického uživatelského rozhraní v Pythonu s využitím knihovny PySimpleGUI

2. Knihovna PySimpleGUI

3. Instalace knihovny PySimpleGUI

4. Zobrazení prázdného okna s nastavenou velikostí a titulkem

5. Smyčka událostí

6. Přidání prvku GUI do okna

7. Automatické přizpůsobení velikosti okna ovládacím prvkům

8. Uspořádání většího množství ovládacích prvků v okně

9. Dialog s informačním textem a potvrzujícím tlačítkem

10. Hodnoty vracené metodou window.read

11. Reakce na stisk konkrétního tlačítka

12. Problematika pravidelného rozmístění GUI prvků v okně

13. Specifikace rozměrů prvků

14. Další standardní ovládací prvky

15. Dialog s dalšími ovládacími prvky

16. Změna (barvového) tématu

17. Výpis všech dostupných barvových témat

18. Obsah navazujícího článku

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Tvorba grafického uživatelského rozhraní v Pythonu s využitím knihovny PySimpleGUI

V předchozích čtyřiceti částech seriálu o tvorbě aplikací s grafickým uživatelským rozhraním v Pythonu jsme si nejprve popsali knihovnu Tkinter (ta je v Pythonu standardem pro tvorbu GUI) a následně pak i knihovnu nazvanou appJar, která je na Tkinteru založena a umožňuje snadnou tvorbu aplikací s jednodušším grafickým uživatelským rozhraním.

Obrázek 1: appJar podporuje i relativně složité ovládací prvky, jakými jsou například stromy.

Zabývali jsme se i aplikacemi psanými v Pythonu, které pro GUI (ale i pro další oblasti) používají vazbu na populární framework Qt. Přitom existuje hned několik možností, jak propojit Python a Qt. Základ tvoří knihovny PyQt (s duální licencí GNU GPL v3 a Riverbank Commercial License) a PySide (s licencí LGPL) pro Qt ≤ 4.8, další možností je PySide2 určená pro Qt 5.x a PySide6 pro verzi 6.x (číslování je poněkud divné, ale od verze 6 alespoň logické).

Obrázek 2: Aplikace naprogramovaná v PySide s nastaveným stylem Cleanlooks.

Ovšem vývoj knihoven určených pro tvorbu grafického uživatelského rozhraní se v posledních několika letech posunul, a to v několika různých směrech. Poměrně často se nyní můžeme setkat s frameworkem Kivy. Jedná se vlastně o ucelenou platformu určenou především pro tvorbu aplikací pro mobilní platformy, tedy pro Android a iOS. Ve skutečnosti je ale možné Kivy použít i na běžných desktopech s operačními systémy Mac OS X, Microsoft Windows a samozřejmě (a to v neposlední řadě) i s Linuxem. V tomto případě však nebudou k dispozici všechny možnosti ovládání, především rozhraní multitouch určené primárně pro dotykové obrazovky. Už z této poznámky je asi zřejmé, že se Kivy bude v mnoha ohledech odlišovat od všech výše uvedených knihoven a frameworků, které jsou určeny především pro běžné desktopy ovládané kombinací klávesnice a myši. Kivy však jde ještě dále, protože programátorům nabízí prakticky všechny technologie, které jsou pro moderní GUI aplikace vyžadovány. A protože se jedná o knihovnu určenou především pro mobilní zařízení, je podporována i OpenGL ES 2, takže vykreslování ovládacích prvků je akcelerováno. Navíc je možné pro deklaraci GUI použít speciální jazyk nazvaný Kv, který zde hraje podobnou roli jako například QML (Qt Modeling Language).

Obrázek 3: Kivy se soustředí spíše na tvorbu GUI pro mobilní telefony a tablety s multitouch ovládáním. Nicméně lze použít i pro tvorbu desktopových aplikací.

Částečně podobným směrem se vydala i knihovna DearPyGui, k níž se (stejně jako ke Kivy) ještě vrátíme.

2. Knihovna PySimpleGUI

Ovšem souběžně s Kivy a DearPyGui vznikají i knihovny jdoucí poněkud odlišným směrem. Konkrétně ke snadné tvorbě grafických uživatelských rozhraní, a to i pro ty uživatele, kteří nejsou profesionálními vývojáři. Jeden příklad takového přístupu už jsme ostatně viděli – je jím výše zmíněná knihovna appJar. A druhou knihovnou, která je v současnosti známější a má i lépe zapamatovatelné jméno (což je poměrně důležité), je knihovna nazvaná PySimpleGUI.

Jedná se o knihovnu, která okna ani jednotlivé ovládací prvky nekreslí s využitím vlastního programového kódu. Namísto toho využívá možností poskytovaných jinými knihovnami: tkinter (základ), Pyside2, wxPython či Remi (ta zajišťuje běh ve webovém prohlížeči – k tomu se dostaneme příště). Toto řešení sice mezi programátora a GUI přidává další vrstvu abstrakce, ale přináší to i několik výhod. Například je možné PySimpleGUI provozovat pouze na počítači se standardní instalací Pythonu, kde lze předpokládat existenci tkinteru. A ve chvíli, kdy je rozhodnuto, že se má z desktopové aplikace stát aplikace běžící ve webovém prohlížeči, bude tato konverze možná (i když prozatím s omezeními).

Se základními možnostmi poskytovanými touto knihovnou se seznámíme v dnešním článku.

3. Instalace knihovny PySimpleGUI

Pokud se spokojíme s tím, že PySimpleGUI bude vykreslovat okna i ovládací prvky s využitím standardní GUI knihovny tkinter, je její instalace snadná a rychlá. Instalaci provedeme, ostatně jako již mnohokrát, pouze pro přihlášeného uživatele:

$ pip3 install --user pysimplegui
 
Collecting pysimplegui
  Downloading PySimpleGUI-4.60.5-py3-none-any.whl (512 kB)
     |████████████████████████████████| 512 kB 1.7 MB/s
Installing collected packages: pysimplegui
Successfully installed pysimplegui-4.60.5

Po instalaci by se měl v adresáři s nainstalovanými balíčky Pythonu objevit i podadresář PySimpleGUI:

$ ls -1h .local/lib/python3.8/site-packages/PySimpleGUI
 
total 1,8M
total 1,8M
-rw-rw-r-- 1 ptisnovs ptisnovs   88 Dec 21 12:54 __init__.py
drwxrwxr-x 2 ptisnovs ptisnovs 4,0K Dec 21 12:54 __pycache__
-rw-rw-r-- 1 ptisnovs ptisnovs 1,8M Dec 21 12:54 PySimpleGUI.py

Zvláštní je, že celý zdrojový kód knihovny PySimpleGUI je uložen v jediném souboru o velikosti 1,8 MB.

4. Zobrazení prázdného okna s nastavenou velikostí a titulkem

Popis většiny GUI knihoven pro Python jsme začínali demonstračním příkladem, v němž se vykreslilo prázdné okno s titulkem. V případě knihovny PySimpleGUI je to snadné. Postačují jen čtyři kroky. V prvním kroku musíme vytvořit prázdný „dvourozměrný“ seznam, do něhož budeme později vkládat jednotlivé ovládací prvky:

# ovládací prvky, které se mají zobrazit v okně
layout = [[]]

Ve druhém kroku okno vytvoříme; současně dojde k jeho zobrazení. Povšimněte si, že specifikujeme titulek okna, jeho komponenty (onen prázdný seznam) a můžeme nastavit i jeho velikost:

# vytvoření okna s ovládacími prvky
window = sg.Window("Window #1", layout, size=(320, 240))

Obrázek 4: Výsledné okno zobrazené na desktopu.

Aby nebyl program ihned ukončen, musíme realizovat čekání na nějakou akci uživatele (což bude pravděpodobně uzavření okna). Prozatím nebudeme implementovat plnohodnotnou smyčku událostí, ale pouze čekání na jedinou událost:

# čekání na událost
window.read()

A nakonec je vhodné okno zavřít:

# po vzniku událostí aplikaci ukončíme
window.close()

Celý program se tedy vlastně skládá z pouhých pěti řádků (včetně importu balíčku PySimpleGUI):

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [[]]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #1", layout, size=(320, 240))
 
# čekání na událost
window.read()
 
# po vzniku událostí aplikaci ukončíme
window.close()

5. Smyčka událostí

V některých aplikacích se s okny pracuje jako s jednoduchými dialogy, v nichž se jen čeká na jedinou akci provedenou uživatelem (stisk tlačítka Yes atd.). Ovšem například hlavní okno aplikace musí umět reagovat na větší množství událostí. V takovém případě již musíme implementovat smyčku s obsluhou událostí (event loop). Její nejjednodušší varianta může vypadat následovně:

# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
 
    # reakce na událost "uzavření okna"
    if event == sg.WIN_CLOSED:
        break

Jedná se tedy o „nekonečnou“ smyčku, v níž čteme události v pořadí, jak přichází a reagujeme na ně. Prozatím rozpoznáváme jen jedinou událost a tou je uzavření okna (hodnotu values prozatím ignorujeme).

Upravený příklad může vypadat následovně:

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [[]]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #1", layout, size=(320, 240))
 
# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
 
    # reakce na událost "uzavření okna"
    if event == sg.WIN_CLOSED:
        break
 
# po výskuku ze smyčky událostí aplikaci ukončíme
window.close()

6. Přidání prvku GUI do okna

Nyní do okna přidáme nějaký GUI prvek (widget). Může se jednat o jednoduché textové návěští (label). Jeho přidání do okna je snadné, protože v parametru layout se předává dvourozměrný seznam, v němž každý prvek seznamu odpovídá „řádku“ v okně. Prvkem takového seznamu je další seznam s jednotlivými ovládacími prvky (widgety). Ty budou umístěny na řádku za sebou.

Vzhledem k tomu, že do okna přidáváme jen jediný ovládací prvek, vložíme ho na první řádek a bude se jednat o jediný prvek na řádku. Výsledkem tedy bude seznam obsahující další seznam s jediným prvkem, což můžeme zapsat následovně:

# ovládací prvky, které se mají zobrazit v okně
layout = [[sg.Text("Hello, world!")]]

Popř. si můžeme tento seznam definovat na více programových řádcích (což bude později vhodnější i přehlednější):

# ovládací prvky, které se mají zobrazit v okně
layout = [
    [
        sg.Text("Hello, world!"),
    ],
]

Takto by mělo vypadat okno, do něhož bylo vloženo textové návěští:

Obrázek 5: Okno s jediným GUI prvkem.

Pro jistotu si ještě ukažme úplný zdrojový kód takto rozšířeného příkladu:

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [[sg.Text("Hello, world!")]]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #2", layout, size=(320, 240))
 
# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
 
    # reakce na událost "uzavření okna"
    if event == sg.WIN_CLOSED:
        break
 
# po výskuku ze smyčky událostí aplikaci ukončíme
window.close()

7. Automatické přizpůsobení velikosti okna ovládacím prvkům

V předchozích demonstračních příkladech jsme vždy explicitně specifikovali velikost okna. To není ve chvíli, kdy okno již obsahuje nějaké ovládací prvky, nezbytně nutné. Velikost okna se totiž dokáže automaticky přizpůsobit prvkům (jejich velikosti a rozmístění). Příkaz pro vytvoření okna tedy můžeme zkrátit na:

# vytvoření okna s ovládacími prvky
window = sg.Window("Window #3", layout)

Výsledek by mohl vypadat následovně:

Obrázek 6: Automatické přizpůsobení velikosti okna prvkům.

Opět si pro úplnost ukažme celý zdrojový kód takto upraveného demonstračního příkladu:

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [[sg.Text("Hello, world!")]]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #3", layout)
 
# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
 
    # reakce na událost "uzavření okna"
    if event == sg.WIN_CLOSED:
        break
 
# po výskuku ze smyčky událostí aplikaci ukončíme
window.close()

8. Uspořádání většího množství ovládacích prvků v okně

Připomeňme si, že ovládací prvky (widgety) jsou v okně uspořádány do pomyslných řádků, přičemž na každém řádku může být uvedeno větší množství těchto prvků. A jednotlivé pomyslné řádky jsou na sobě nezávislé – není zde tedy použit koncept mřížky (grid). To sice může na první pohled vypadat jako poměrně primitivní způsob práce s rozmístěním prvků na okně (layout), ale příště uvidíme, že to pro mnoho účelů může být plně postačující.

Ukažme si nepatrně složitější GUI okno, v němž budou umístěny čtyři ovládací prvky. Na prvním řádku bude textové návěští a tlačítko. Na druhém řádku bude vstupní textové políčko a na řádku třetím pak dvě další tlačítka se specifickým významem: odeslání dat a zrušení operace. Díky použití „seznamu seznamů“ je specifikace obsahu takového okna skutečně jednoduchá:

layout = [
    [sg.Text("Hello, world!"), sg.Button("Button1")],
    [sg.InputText()],
    [sg.Submit(), sg.Cancel()],
]

Výsledek:

Obrázek 7: Okno, do něhož jsou umístěny čtyři ovládací prvky.

Celý příklad se přitom rozšířil jen nepatrně, jak je to ostatně patrné z celkového výpisu:

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [sg.Text("Hello, world!"), sg.Button("Button1")],
    [sg.InputText()],
    [sg.Submit(), sg.Cancel()],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #4", layout)
 
# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
 
    # reakce na událost "uzavření okna"
    if event == sg.WIN_CLOSED:
        break
 
# po výskoku ze smyčky událostí aplikaci ukončíme
window.close()

9. Dialog s informačním textem a potvrzujícím tlačítkem

Již v předchozím textu jsme si řekli, že v aplikacích je mnohdy zapotřebí zobrazovat různé dialogy a nikoli plnohodnotná interaktivní okna. Dialog může být realizován snadno – vytvoříme okno s libovolnými GUI prvky, ovšem nebudeme realizovat celou smyčku událostí. Namísto ní pouze zavoláme metodu window.read() a popř. zpracujeme událost, která vznikla (viz dále). Ukažme si tedy způsob vytvoření tohoto dialogu:

Obrázek 8: Dialog s informačním textem a potvrzujícím tlačítkem.

Samotný skript, který tento dialog vytvoří, vypadá takto:

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [sg.Text("Hello, world!")],
    [sg.Submit("okay")],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #5", layout)
 
# čekání na uzavření okna
window.read()
 
# po přečtení události můžeme okno zavřít
window.close()
Poznámka: později si ještě ukážeme, jak u těchto oken-dialogů specifikovat modálnost.

10. Hodnoty vracené metodou window.read

Prozatím jsme v příkladech používali značně zjednodušenou formu smyčky událostí, v níž jsme reagovali pouze na událost typu „uzavření okna“:

# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
 
    # reakce na událost "uzavření okna"
    if event == sg.WIN_CLOSED:
        break

Ovšem zajímavé bude zjistit, jaké další hodnoty se vrací a ukládají do lokálních proměnných event a values. Proto si tyto hodnoty budeme ve smyčce tisknout, a to pro smyčku vytvořenou pro okno se čtyřmi ovládacími prvky:

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [sg.Text("Hello, world!"), sg.Button("Button1")],
    [sg.InputText()],
    [sg.Submit(), sg.Cancel()],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #6", layout)
 
# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
    print("Event: ", event, "    Values: ", values)
 
    # reakce na událost "uzavření okna"
    if event == sg.WIN_CLOSED:
        break
 
# po výskoku ze smyčky událostí aplikaci ukončíme
window.close()

Po stisku prvního tlačítka se vrátí:

Event:  Button1     Values:  {0: ''}

Po zápisu textu do textového pole nezískáme žádnou událost (!), ovšem opětovné stlačení prvního tlačítka nyní vrátí:

Event:  Button1     Values:  {0: 'ahoj'}

To tedy znamená, že ve Values je uložen slovník s hodnotami všech prvků, které mohou udržovat stav. A klíče, jak uvidíme dále, lze specifikovat, takže nebude nutné zjišťovat, který prvek odpovídá klíči 0.

Stisk dalších tlačítek mění řetězec uložený do proměnné event:

Event:  Submit     Values:  {0: 'ahoj'}
Event:  Cancel     Values:  {0: 'ahoj'}

A konečně událost „uzavření okna“ je odlišná, protože obě vracené hodnoty budou None:

Event:  None     Values:  None

11. Reakce na stisk konkrétního tlačítka

Nyní již vlastně víme, jak můžeme ve smyčce událostí zareagovat na stisk konkrétního tlačítka, protože se jeho označení vrátí přímo v první návratové hodnotě metody window.read(). Přidejme si tedy do okna tlačítko Exit:

Obrázek 9: Další tlačítko přidané do okna.

V případě, že uživatel stiskne tlačítko Exit, ukončíme smyčku událostí a zavřeme okno (viz zvýrazněný text):

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [sg.Text("Hello, world!"), sg.Button("Button1")],
    [sg.InputText()],
    [sg.Submit(), sg.Cancel(), sg.Exit()],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #7", layout)
 
# obsluha smyčky událostí (event loop)
while True:
    # přečtení události
    event, values = window.read()
    print("Event: ", event, "    Values: ", values)
 
    # reakce na událost "uzavření okna"
    if event in {sg.WIN_CLOSED, "Exit"}:
        break
 
# po výskoku ze smyčky událostí aplikaci ukončíme
window.close()

Důležité je, že v tomto případě stále můžeme získat hodnotu zapsanou do textového políčka:

Event:  Exit     Values:  {0: 'ahoj'}

12. Problematika pravidelného rozmístění GUI prvků v okně

V předchozím textu jsme si řekli, že prvky v okně jsou rozmístěny na pomyslných řádcích. Jednotlivé řádky jsou přitom na sobě nezávislé, což znamená, že může být (na první pohled) poněkud problematické vertikální zarovnání prvků. Ostatně si to můžeme ukázat na dialogu pro zadání jména a příjmení (povšimněte si specifikace klíčů u obou vstupních textových polí):

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [sg.Text("Name"), sg.InputText(key="name")],
    [sg.Text("Surname"), sg.InputText(key="surname")],
    [sg.Submit()],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #8", layout)
 
# přečtení jediné události
event, values = window.read()
print("Event: ", event, "    Values: ", values)
 
# po přečtení události okno zavřeme
window.close()

Výsledkem bude okno, v němž nejsou prvky rozmístěny příliš elegantně ani přehledně:

Obrázek 10: Dialog pro zadání jména a příjmení.

13. Specifikace rozměrů prvků

Výše uvedený problém lze řešit buď využitím kontejnerů pro prvky (kontejner se přitom chová jako jediný prvek), nebo v jednodušších případech tím, že u některých GUI prvků budeme specifikovat jejich velikost (postačuje nastavit šířku a ponechat výšku nulovou). To nám pomůže zarovnat textová návěští, přičemž vstupní textová pole mají shodnou velikost:

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [sg.Text("Name", size=(8, 0)), sg.InputText(key="name")],
    [sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname")],
    [sg.Submit()],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #9", layout)
 
# přečtení jediné události
event, values = window.read()
print("Event: ", event, "    Values: ", values)
 
# po přečtení události okno zavřeme
window.close()

Takto vypadá výsledek po zobrazení okna:

Obrázek 11: Upravený dialog pro zadání jména a příjmení.

Za povšimnutí stojí i hodnoty vrácené z metody window.read() po vyplnění obou políček a stisku tlačítka Submit:

Event:  Submit     Values:  {'name': 'Pepek', 'surname': 'Vyskoč'}

14. Další standardní ovládací prvky

V knihovně PySimpleGUI máme k dispozici i další ovládací prvky, nejenom textová návěští, textová pole a tlačítka.

Důležitý je ovládací prvek pro zobrazení seznamu voleb. Seznam může být buď neměnitelný (readonly=True) nebo do něj naopak uživatel může zapsat novou hodnotu (takže jde vlastně o textové pole s nápovědou). U tohoto prvku lze navíc zvolit, která z hodnot bude přednastavená při prvním zobrazení okna (default_value=hodnota):

sg.Combo(["Administrator", "Maintainer", "Guest"], default_value="Guest", readonly=True, key="role")

Dalším prvkem je zatrhávací box, u něhož lze volit výchozí hodnotu a případný popisek:

sg.Checkbox("", default=True, key="register e-mail")

A konečně z těch nejpoužívanějších prvků jmenujme sadu prvků, které bývají spojeny do jediné skupiny tvořící „radiová tlačítka“ (což odkazuje na starodávná radia s pevně nastavenou předvolbou stanic pomocí tlačítek – to se vlastně vrátilo zpět). Spojení těchto ovládacích prvků do skupiny je realizováno specifikací této skupiny ve druhém povinném parametru (v našem případě se jedná o skupiny THEME):

sg.Radio("Light", "THEME", default=False, key="light_theme"),
sg.Radio("Dark", "THEME", default=True, key="dark_theme"),

15. Dialog s dalšími ovládacími prvky

Nyní již máme k dispozici všechny znalosti potřebné pro realizaci složitějšího dialogu obsahujícího další ovládací prvky. Prvky jsou opět rozmístěny do řádků. Proto u prvních prvků na každém řádku specifikujeme jeho šířku tak, aby byly prvky umístěné pod sebou vizuálně zarovnány:

Obrázek 12: Dialog s dalšími ovládacími prvky.

A takto vypadá celý program. Stále by měl být poměrně dobře čitelný (v porovnání s některými jinými GUI toolkity):

import PySimpleGUI as sg
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [
        sg.Text("Name", size=(8, 0)),
        sg.InputText(key="name")
    ],
    [
        sg.Text("Surname", size=(8, 0)),
        sg.InputText(key="surname")
    ],
    [
        sg.Text("Role", size=(8, 0)),
        sg.Combo(["Administrator", "Maintainer", "Guest"], default_value="Guest", readonly=True, key="role")
    ],
    [
        sg.Text("Register e-mail", size=(8, 0)),
        sg.Checkbox("", default=True, key="register e-mail")
    ],
    [
        sg.Text("Color theme", size=(8, 0)),
        sg.Radio("Light", "THEME", default=False, key="light_theme"),
        sg.Radio("Dark", "THEME", default=True, key="dark_theme"),
    ],
    [
        sg.Submit()
    ],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #9", layout)
 
# přečtení jediné události
event, values = window.read()
print("Event: ", event, "    Values: ", values)
 
# po přečtení události okno zavřeme
window.close()

Zajímavé bude zjistit, jaké hodnoty se vypíšou po stisku potvrzujícího tlačítka:

Event:  Submit     Values:  {'name': 'Pepek', 'surname': 'Vyskoč', 'role': 'Administrator', 'register e-mail': True, 'light_theme': True, 'dark_theme': False}

Zpracování slovníku values by tedy mělo být pro každého vývojáře již relativně snadným úkolem.

16. Změna (barvového) tématu

Výchozí barvové téma, které je nastaveno při spuštění aplikace, je možné snadno změnit, ovšem ještě před zobrazením okna. Provede se to zavoláním funkce PySimpleGUI.theme, kterému se předá řetězec s názvem požadovaného barvového schématu. Můžeme například zvolit barvové schéma nazvané „DarkAmber“:

# nastavení odlišného tématu
sg.theme('DarkAmber')

Nyní by měl celý dialog vypadat odlišně:

Obrázek 13: Dialog s dalšími ovládacími prvky po změně barvového tématu.

Volání PySimpleGUI.theme() provedeme ještě před vytvořením okna, jak je to patrné z výpisu celého zdrojového kódu demonstračního příkladu:

import PySimpleGUI as sg
 
# nastavení odlišného tématu
sg.theme('DarkAmber')
 
# ovládací prvky, které se mají zobrazit v okně
layout = [
    [
        sg.Text("Name", size=(8, 0)),
        sg.InputText(key="name")
    ],
    [
        sg.Text("Surname", size=(8, 0)),
        sg.InputText(key="surname")
    ],
    [
        sg.Text("Role", size=(8, 0)),
        sg.Combo(["Administrator", "Maintainer", "Guest"], default_value="Guest", readonly=True, key="role")
    ],
    [
        sg.Text("Register e-mail", size=(8, 0)),
        sg.Checkbox("", default=True, key="register e-mail")
    ],
    [
        sg.Text("Color theme", size=(8, 0)),
        sg.Radio("Light", "THEME", default=False, key="light_theme"),
        sg.Radio("Dark", "THEME", default=True, key="dark_theme"),
    ],
    [
        sg.Submit()
    ],
]
 
# vytvoření okna s ovládacími prvky
window = sg.Window("Window #9", layout)
 
# přečtení jediné události
event, values = window.read()
print("Event: ", event, "    Values: ", values)
 
# po přečtení události okno zavřeme
window.close()

17. Výpis všech dostupných barvových témat

Jména všech dostupných barvových témat jsou uložena jako klíče slovníku PySimpleGUI.LOOK_AND_FEEL_TABLE (hodnotami jsou pak jednotlivé části GUI), takže seznam témat je možné získat takto:

import PySimpleGUI as sg
 
themes = sorted(sg.LOOK_AND_FEEL_TABLE.keys())
 
print("\n".join(themes))

Alternativně lze zavolat funkci PySimpleGUI.list_of_look_an­d_feel_values(), která vrátí seznam všech dostupných témat:

import PySimpleGUI as sg
 
themes = sorted(sg.list_of_look_and_feel_values())
 
print("\n".join(themes))

Výsledkem bude v obou případech stejný seznam dostupných barvových témat, která lze například nabídnout uživateli (což si ukážeme příště):

Black
BlueMono
BluePurple
BrightColors
BrownBlue
Dark
Dark2
DarkAmber
DarkBlack
DarkBlack1
DarkBlue
DarkBlue1
DarkBlue10
DarkBlue11
DarkBlue12
DarkBlue13
DarkBlue14
DarkBlue15
DarkBlue16
DarkBlue17
DarkBlue2
DarkBlue3
DarkBlue4
DarkBlue5
DarkBlue6
DarkBlue7
DarkBlue8
DarkBlue9
DarkBrown
DarkBrown1
DarkBrown2
DarkBrown3
DarkBrown4
DarkBrown5
DarkBrown6
DarkBrown7
DarkGreen
DarkGreen1
DarkGreen2
DarkGreen3
DarkGreen4
DarkGreen5
DarkGreen6
DarkGreen7
DarkGrey
DarkGrey1
DarkGrey10
DarkGrey11
DarkGrey12
DarkGrey13
DarkGrey14
DarkGrey15
DarkGrey2
DarkGrey3
DarkGrey4
DarkGrey5
DarkGrey6
DarkGrey7
DarkGrey8
DarkGrey9
DarkPurple
DarkPurple1
DarkPurple2
DarkPurple3
DarkPurple4
DarkPurple5
DarkPurple6
DarkPurple7
DarkRed
DarkRed1
DarkRed2
DarkTanBlue
DarkTeal
DarkTeal1
DarkTeal10
DarkTeal11
DarkTeal12
DarkTeal2
DarkTeal3
DarkTeal4
DarkTeal5
DarkTeal6
DarkTeal7
DarkTeal8
DarkTeal9
Default
Default1
DefaultNoMoreNagging
GrayGrayGray
Green
GreenMono
GreenTan
HotDogStand
Kayak
LightBlue
LightBlue1
LightBlue2
LightBlue3
LightBlue4
LightBlue5
LightBlue6
LightBlue7
LightBrown
LightBrown1
LightBrown10
LightBrown11
LightBrown12
LightBrown13
LightBrown2
LightBrown3
LightBrown4
LightBrown5
LightBrown6
LightBrown7
LightBrown8
LightBrown9
LightGray1
LightGreen
LightGreen1
LightGreen10
LightGreen2
LightGreen3
LightGreen4
LightGreen5
LightGreen6
LightGreen7
LightGreen8
LightGreen9
LightGrey
LightGrey1
LightGrey2
LightGrey3
LightGrey4
LightGrey5
LightGrey6
LightPurple
LightTeal
LightYellow
Material1
Material2
NeutralBlue
Purple
Python
PythonPlus
Reddit
Reds
SandyBeach
SystemDefault
SystemDefault1
SystemDefaultForReal
Tan
TanBlue
TealMono
Topanga

18. Obsah navazujícího článku

Prozatím již víme, jak lze s využitím knihovny PySimpleGUI vytvořit okno či dialog se základními prvky GUI. Ovšem pro tvorbu aplikací se složitějšími dialogy je nutné umět lépe rozmisťovat jednotlivé ovládací prvky na ploše oken a dialogů. K tomuto účelu slouží takzvané kontejnery, které si popíšeme příště. Taktéž si ukážeme využití kreslicí plochy a v neposlední řadě i způsob naprogramování reakce na události, které vzniknou například ihned po výběru prvku ve výběrovém boxu (v takovém případě totiž PySimpleGUI ve výchozím nastavení žádnou událost nevytváří).

bitcoin_skoleni

Obrázek 14: Nepatrně složitější aplikace s GUI, která je součástí samotného balíčku PySimpleGUI.

19. Repositář s demonstračními příklady

Všechny Pythonovské skripty, které jsme si v dnešním článku ukázali, naleznete na adrese https://github.com/tisnik/most-popular-python-libs. Následují odkazy na jednotlivé příklady. Pro jejich spuštění je pochopitelně nutné mít nainstalován balíček PySimpleGUI:

# Příklad Stručný popis Adresa příkladu
1 01-empty-window.py prázdné okno https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/01-empty-window.py
2 02-empty-window-event-loop.py prázdné okno, implementace klasické smyčky událostí https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/02-empty-window-event-loop.py
3 03-window-with-text-label.py okno se specifikovanou velikostí a s vloženým textovým prvkem https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/03-window-with-text-label.py
4 04-window-with-text-label.py okno s automaticky vypočtenou velikostí a s vloženým textovým prvkem https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/04-window-with-text-label.py
5 05-more-controls.py pětice ovládacích prvků přidaných do okna https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/05-more-controls.py
6 06-info.py informační okno (dialog) bez navázané smyčky událostí https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/06-info.py
7 07-events.py tisk všech zaregistrovaných a přečtených událostí https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/07-events.py
8 08-events-cancel.py tisk zaregistrovaných událostí, reakce na stisk tlačítka Cancel https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/08-events-cancel.py
9 09-one-shot-window.py dialog pro zadání údajů do textových políček, bez smyčky událostí https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/09-one-shot-window.py
10 10-sizing.py explicitní nastavení velikostí jednotlivých ovládacích prvků https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/10-sizing.py
11 11-even-more-controls.py přidání dalších ovládacích prvků do okna https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/11-even-more-controls.py
12 12-different-theme.py nastavení odlišného barvového tématu https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/12-different-theme.py
13 13-print-themes.py tisk jmen všech dostupných témat https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/13-print-themes.py
14 14-print-themes-2.py tisk jmen všech dostupných témat, lepší varianta https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/14-print-themes-2.py
15 15-select-theme.py interaktivní změna tématu https://github.com/tisnik/most-popular-python-libs/blob/master/PySimpleGUI/15-select-theme.py

20. Odkazy na Internetu

  1. PySimpleGUI
    https://www.pysimplegui.or­g/en/latest/
  2. Kivy na GitHubu
    https://github.com/kivy/kivy
  3. DearPyGui na GitHubu
    https://github.com/hoffstad­t/DearPyGui
  4. Dokumentace ke knihovně DearPyGui
    https://dearpygui.readthe­docs.io/en/latest/index.html#
  5. The Hitchhiker's Guide to Pyhton: GUI Applications
    http://docs.python-guide.org/en/latest/scenarios/gui/
  6. 7 Top Python GUI Frameworks for 2017
    http://insights.dice.com/2014/11/26/5-top-python-guis-for-2015/
  7. Stránky projektu wxPython
    https://wxpython.org/
  8. wxPython Project Phoenix (na GitHubu)
    https://github.com/wxWidget­s/Phoenix/blob/wxPython-4.0.3/README.rst
  9. wxPython API Documentation
    https://docs.wxpython.org/index.html
  10. wxWidgets
    https://wxwidgets.org/
  11. wxPython 4.0.3 na PyPi
    https://pypi.org/project/wxPyt­hon/4.0.3/
  12. wxGlade – a GUI builder for wxWidgets
    http://wxglade.sourceforge.net/
  13. Repositář projektu wxGlade
    https://github.com/wxGlade/wxGlade/
  14. wxGlade’s documentation
    http://wxglade.sourceforge­.net/docs/index.html
  15. Graphical User Interfaces (GUI)
    https://pythonspot.com/gui/
  16. wxPyWiki
    https://wiki.wxpython.org/FrontPage
  17. Getting started with wxPython
    https://wiki.wxpython.org/Get­ting%20Started#A_First_Ap­plication:_.22Hello.2C_Wor­ld.22
  18. wxPython GUI tutorial
    https://pythonspot.com/wxpython-gui-tutorial/
  19. wxPython tutorial
    http://zetcode.com/wxpython/
  20. Build wxPython On Raspberry Pi
    https://wiki.wxpython.org/Bu­ildWxPythonOnRaspberryPi
  21. wxPython History
    https://wxpython.org/pages/his­tory/index.html
  22. Installing wxPython 4.0 (Project Phoenix) on Fedora 27
    https://blog.wizardsofthe­web.pro/installing-wxpython-on-fedora/
  23. Category:Software that uses wxWidgets
    https://en.wikipedia.org/wi­ki/Category:Software_that_u­ses_wxWidgets
  24. Hra Breakout napísaná v Tkinteri
    https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/
  25. GUI Programming in Python
    https://wiki.python.org/mo­in/GuiProgramming
  26. Cameron Laird's personal notes on Python GUIs
    http://phaseit.net/claird/com­p.lang.python/python_GUI.html
  27. Python GUI development
    http://pythoncentral.io/introduction-python-gui-development/
  28. Hand Coded GUI Versus Qt Designer GUI
    https://stackoverflow.com/qu­estions/387092/hand-coded-gui-versus-qt-designer-gui
  29. Qt Creator Manual
    http://doc.qt.io/qtcreator/
  30. Qt Designer Manual
    http://doc.qt.io/qt-5/qtdesigner-manual.html
  31. Qt Creator (Wikipedia)
    https://en.wikipedia.org/wi­ki/Qt_Creator
  32. QIODevice
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/QI­ODevice.html#PySide.QtCore­.QIODevice
  33. QFile
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/QFi­le.html#PySide.QtCore.QFi­le
  34. QUiLoader
    https://pyside.github.io/doc­s/pyside/PySide/QtUiTools/QU­iLoader.html#PySide.QtUiTo­ols.PySide.QtUiTools.QUiLo­ader.load
  35. QSvgWidget
    https://pyside.github.io/doc­s/pyside/PySide/QtSvg/QSvgWid­get.html
  36. QByteArray
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/QBy­teArray.html
  37. Differences Between PySide and PyQt
    https://wiki.qt.io/Differen­ces_Between_PySide_and_PyQt
  38. PySide 1.2.1 tutorials
    https://pyside.github.io/doc­s/pyside/tutorials/index.html
  39. PySide tutorial
    http://zetcode.com/gui/py­sidetutorial/
  40. Drawing in PySide
    http://zetcode.com/gui/py­sidetutorial/drawing/
  41. Qt Core
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/Qt­.html
  42. Signals & Slots
    http://doc.qt.io/qt-4.8/signalsandslots.html
  43. Signals and Slots in PySide
    http://wiki.qt.io/Signals_an­d_Slots_in_PySide
  44. Intro to PySide/PyQt: Basic Widgets and Hello, World!
    http://www.pythoncentral.io/intro-to-pysidepyqt-basic-widgets-and-hello-world/
  45. Leo editor
    http://leoeditor.com/
  46. IPython Qt Console aneb vylepšený pseudoterminál
    https://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-ipython-a-ipython-notebook/#k06
  47. Python GUI development
    http://pythoncentral.io/introduction-python-gui-development/
  48. Graphic User Interface FAQ
    https://docs.python.org/2/faq/gu­i.html#graphic-user-interface-faq
  49. TkInter
    https://wiki.python.org/moin/TkInter
  50. Tkinter 8.5 reference: a GUI for Python
    http://infohost.nmt.edu/tcc/hel­p/pubs/tkinter/web/index.html
  51. TkInter (Wikipedia)
    https://en.wikipedia.org/wiki/Tkinter
  52. appJar
    http://appjar.info/
  53. appJar (Wikipedia)
    https://en.wikipedia.org/wiki/AppJar
  54. appJar na Pythonhosted
    http://pythonhosted.org/appJar/
  55. appJar widgets
    http://appjar.info/pythonWidgets/
  56. Stránky projektu PyGTK
    http://www.pygtk.org/
  57. PyGTK (Wikipedia)
    https://cs.wikipedia.org/wiki/PyGTK
  58. Stránky projektu PyGObject
    https://wiki.gnome.org/Pro­jects/PyGObject
  59. Stránky projektu Kivy
    https://kivy.org/#home
  60. Stránky projektu PyQt
    https://riverbankcomputin­g.com/software/pyqt/intro

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.