Obsah
1. Tvorba grafického uživatelského rozhraní v Pythonu s využitím knihovny PySimpleGUI (2)
2. Interaktivní výběr barevného tématu aplikace v GUI
3. Změna tématu ihned po jeho výběru z výběrového boxu
4. Výchozí zarovnání prvků v okně či kontejneru
5. Vycentrování prvků a zarovnání prvků doprava
6. Neviditelný prvek typu „pružina“
7. Další typ kontejneru – Column
8. Kontejnery je možné vložit do jiných kontejnerů
9. Vizuální oddělení GUI prvků
11. Přidání hlavního menu do okna aplikace
12. Přidání stavového řádku do okna aplikace
13. Vlastní způsob vykreslení titulku okna
16. Přidání kreslicího plátna do okna aplikace
17. Specifikace velikosti a barvy pozadí kreslicího plátna
19. Repositář s demonstračními příklady
1. Tvorba grafického uživatelského rozhraní v Pythonu s využitím knihovny PySimpleGUI (2)
V úvodním článku o knihovně PySimpleGUI jsme se dozvěděli, jak je možné 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 dnes. 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áří, což může být pro některé typy aplikací omezující).
2. Interaktivní výběr barevného tématu aplikace v GUI
Podívejme se nyní na způsob realizace výběru barevného tématu (ze všech dostupných témat) přímo z GUI aplikace. Je to relativně snadné. Nejdříve získáme jména všech témat postupem, který již známe z minula:
themes = sorted(sg.list_of_look_and_feel_values())
Posléze do okna aplikace vložíme ovládací GUI prvek Combo, nastavíme jeho jméno (resp. klíč), seznam všech témat a výchozí téma, které má být v prvku předvybrané:
sg.Combo(themes, default_value=selected_theme, readonly=True, key="theme")
A konečně ve smyčce událostí zajistíme, že když uživatel nějaké téma vybere a stiskne tlačítko Change, bude stávající okno zavřeno, změní se téma a vytvoří se okno nové:
# obsluha smyčky událostí (event loop) while True: # přečtení události event, values = window.read() # reakce na výběr tématu if event == "Change": selected_theme = values["theme"] window.close() window = main_window(selected_theme)
Výsledky mohou vypadat takto:
Obrázek 1: Interaktivní výběr barevného tématu.
Obrázek 2: Interaktivní výběr barevného tématu.
Obrázek 3: Interaktivní výběr barevného tématu.
Pro úplnost si ukažme celý zdrojový kód demonstračního příkladu:
import PySimpleGUI as sg themes = sorted(sg.list_of_look_and_feel_values()) # vytvoření okna s ovládacími prvky def main_window(theme=None): selected_theme = theme or themes[0] # ovládací prvky, které se mají zobrazit v okně layout = [ [ sg.Text("Theme"), sg.Combo(themes, default_value=selected_theme, readonly=True, key="theme"), ], [ sg.Button("Change"), sg.Cancel("Exit") ], ] sg.theme(selected_theme) return sg.Window("Window #4", layout) window = main_window() # 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 in {sg.WIN_CLOSED, "Exit"}: break # reakce na výběr tématu if event == "Change": selected_theme = values["theme"] window.close() window = main_window(selected_theme) # po výskoku ze smyčky událostí aplikaci ukončíme window.close()
3. Změna tématu ihned po jeho výběru z výběrového boxu
V demonstračním příkladu, který byl popsán v předchozí kapitole, bylo nutné téma nejdříve vybrat a poté stisknout tlačítko Change. To může být poněkud nepraktické, ovšem GUI prvek Combo ve svém výchozím nastavení negeneruje žádné události, takže je nutné generování událostí nejprve povolit. Ve skutečnosti je to velmi jednoduché, protože u tohoto ovládacího prvku postačí specifikace nepovinného parametru enable_events:
sg.Combo(themes, default_value=selected_theme, readonly=True, key="theme", enable_events=True)
Z okna odstraníme tlačítko Change (je už zbytečné) a upravíme smyčku událostí takovým způsobem, aby reagovala na událost „theme“ (což je jméno, resp. klíč kombo boxu):
# 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 in {sg.WIN_CLOSED, "Exit"}: break # reakce na výběr tématu if event == "theme": selected_theme = values["theme"] window.close() window = main_window(selected_theme)
Výsledky:
Obrázek 4: Interaktivní výběr barevného tématu upravenou aplikací.
Obrázek 5: Interaktivní výběr barevného tématu upravenou aplikací.
Obrázek 6: Interaktivní výběr barevného tématu upravenou aplikací.
Opět se pro úplnost podívejme na celý zdrojový kód takto upravené aplikace:
import PySimpleGUI as sg themes = sorted(sg.list_of_look_and_feel_values()) # vytvoření okna s ovládacími prvky def main_window(theme=None): selected_theme = theme or themes[0] # ovládací prvky, které se mají zobrazit v okně layout = [ [ sg.Text("Theme"), sg.Combo(themes, default_value=selected_theme, readonly=True, key="theme", enable_events=True), ], [ sg.Cancel("Exit") ], ] sg.theme(selected_theme) return sg.Window("Window #4", layout) window = main_window() # 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 in {sg.WIN_CLOSED, "Exit"}: break # reakce na výběr tématu if event == "theme": selected_theme = values["theme"] window.close() window = main_window(selected_theme) # po výskoku ze smyčky událostí aplikaci ukončíme window.close()
4. Výchozí zarovnání prvků v okně či kontejneru
V případě, že budeme vytvářet layout složitějšího dialogu, je mnohdy nutné měnit i zarovnání prvků. Ve výchozím nastavení jsou prvky zarovnány doleva. To si můžeme velmi snadno otestovat spuštěním dalšího skriptu, který zobrazí čtyři GUI prvky (samá tlačítka), z nichž každý je umístěn na samostatném řádku. Jednotlivé prvky mají rozdílnou šířku, takže je jejich zarovnání zcela jasně patrné:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně layout = [ [ sg.Button("S"), ], [ sg.Button("Button"), ], [ sg.Button("Long button"), ], [ sg.Submit() ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #17", 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ýsledné okno by mělo vypadat následovně:
Obrázek 7: Okno se čtyřmi tlačítky zarovnanými doleva.
5. Vycentrování prvků a zarovnání prvků doprava
Zarovnání prvků není vlastností jednotlivých prvků, ale vlastností kontejneru, v nichž jsou prvky umístěny. My prozatím jako kontejner používáme celé okno aplikace, takže zarovnání bude muset být specifikováno zde. Pokusme se například prvky vycentrovat:
window = sg.Window("Window #18", layout, element_justification="c")
Výsledek by měl být odlišný:
Obrázek 8: Okno se čtyřmi tlačítky vycentrovanými tlačítky.
Celý skript vypadá takto:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně layout = [ [ sg.Button("S"), ], [ sg.Button("Button"), ], [ sg.Button("Long button"), ], [ sg.Submit() ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #18", layout, element_justification="c") # 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()
Prvky samozřejmě můžeme nechat zarovnat doprava:
window = sg.Window("Window #18", layout, element_justification="r")
Tentokrát s tímto výsledkem:
Obrázek 9: Okno se čtyřmi tlačítky zarovnanými doprava.
A takto vypadá výsledný skript, který okno s GUI prvky vytvořil a zobrazil:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně layout = [ [ sg.Button("S"), ], [ sg.Button("Button"), ], [ sg.Button("Long button"), ], [ sg.Submit() ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #18", layout, element_justification="r") # 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()
6. Neviditelný prvek typu „pružina“
Kromě viditelných GUI prvků můžeme do okna (kontejneru) přidávat i některé neviditelné prvky. Důležitým prvkem je „pružina“ (Push), která od sebe odsouvá další prvky na stejném řádku. Pokud se na řádku použije více pružin, mají všechny stejnou sílu. To nám umožňuje například vycentrovat prvek tak, že před něj i za něj vložíme pružinu.
Pokusme se nyní na každý řádek vložit dvě tlačítka a vkládat mezi ně (na různé pozice) pružiny:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně layout = [ [ sg.Button("Button1"), sg.Button("Button2"), ], [ sg.Push(), sg.Button("Button1"), sg.Button("Button2"), ], [ sg.Button("Button1"), sg.Push(), sg.Button("Button2"), ], [ sg.Button("Button1"), sg.Button("Button2"), sg.Push(), ], [ sg.Push(), sg.Button("Button1"), sg.Button("Button2"), sg.Push(), ], [ sg.Push(), sg.Button("Button1"), sg.Push(), sg.Button("Button2"), sg.Push(), ], [ sg.Submit() ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #20", layout, size=(320, 240)) # 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 by měly být takto rozmístěné prvky:
Obrázek 10: Tlačítka, mezi které jsou vkládány pružiny.
7. Další typ kontejneru – Column
Poměrně často je vhodné jednotlivé prvky grafického uživatelského rozhraní rozmístit do sloupců a nikoli do řádků. V knihovně PySimpleGUI sice pro tento účel nelze využít „mřížku“ (grid), ovšem programátoři mají k dispozici kontejner nazvaný jednoduše a příznačně Column. Díky tomu, že se jedná o kontejner, lze do něj vkládat další komponenty. Přitom se používá stále stejný koncept – komponenty jsou uloženy v dvourozměrném seznamu. Podívejme se, jak lze komponenty rozdělit do dvou sloupců:
left_column = [ [první řádek komponent], [druhý řádek komponent], ... ] right_column = [ [první řádek komponent], [druhý řádek komponent], ... ]
Tyto sloupce se vloží na plochu okna stejně, jako jakékoli další komponenty. Pod sloupce je umístěn další řádek s tlačítkem:
layout = [ [ sg.Column(left_column), sg.Column(right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ]
Výsledek může vypadat následovně:
Obrázek 11: Komponenty rozmístěné do dvou sloupců.
Celý zdrojový kód demonstračního příkladu vypadá následovně:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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"), ], ] layout = [ [ sg.Column(left_column), sg.Column(right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #21", 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()
8. Kontejnery je možné vložit do jiných kontejnerů
Kontejnery (kromě vlastních oken) mají jednu důležitou vlastnost – je možné je vkládat (i se všemi komponentami v nich) do dalších kontejnerů. To mj. znamená, že komponenta typu Column může být vložena do dalšího „sloupce“ atd. Tento koncept je ukázán na dalším demonstračním příkladu, kde v pravém sloupci je umístěn další sloupec s komponentami – radiovými tlačítky):
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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.Column([ [sg.Radio("Light", "THEME", default=False, key="light_theme")], [sg.Radio("Dark", "THEME", default=True, key="dark_theme")], ]), ], ] layout = [ [ sg.Column(left_column), sg.Column(right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #22", 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ýsledný design okna:
Obrázek 12: Komponenty rozmístěné do dvou sloupců. V pravém sloupci je jako jedna z komponent umístěn ještě jeden sloupec.
9. Vizuální oddělení GUI prvků
Pro vizuální oddělení prvků grafického uživatelského rozhraní se používají horizontální a vertikální oddělovače (separátory), které jsou představovány pasivními komponentami HSep a VSep. V dalším demonstračním příkladu jsou použity oba typy separátorů tak, aby vzniklo okno s následujícím rozložením:
Obrázek 13: Horizontální a vertikální oddělovače (separátory).
Vertikální separátor je vložen mezi oba sloupce, horizontální separátor pak na samostatný řádek:
layout = [ [ sg.Column(left_column), sg.VSep(), sg.Column(right_column), ], [ sg.HSep(), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ]
Takto vypadá úplný zdrojový kód demonstračního příkladu, který oba typy oddělovačů používá:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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.Column([ [sg.Radio("Light", "THEME", default=False, key="light_theme")], [sg.Radio("Dark", "THEME", default=True, key="dark_theme")], ]), ], ] layout = [ [ sg.Column(left_column), sg.VSep(), sg.Column(right_column), ], [ sg.HSep(), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #23", 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()
10. Rámce (Frame)
V případě, že se namísto kontejneru Column použije kontejner Frame, budou komponenty umístěné na tento kontejner orámovány. Navíc je možné každý pro každý rámec (frame) specifikovat jeho titulek, takže rozvržení celého okna (dialogu) můžeme realizovat i takto:
layout = [ [ sg.Frame("User", left_column), sg.Frame("Settings", right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ]
S výsledkem:
Obrázek 14: Komponenty umístěné do rámců (frames).
A pro úplnost si ukažme úplný zdrojový kód takto upraveného demonstračního příkladu:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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.Column([ [sg.Radio("Light", "THEME", default=False, key="light_theme")], [sg.Radio("Dark", "THEME", default=True, key="dark_theme")], ]), ], ] layout = [ [ sg.Frame("User", left_column), sg.Frame("Settings", right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #24", 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()
11. Přidání hlavního menu do okna aplikace
Knihovna PySimpleGUI pochopitelně podporuje i specifikaci menu. Přímo na plochu okna (v jeho horní části, jak je zvykem) se umisťuje hlavní menu, které je realizováno komponentou nazvanou jednoduše Menu:
layout = [ [sg.Menu(menu)], ... ... ... ]
Samotné menu je pak v tom nejjednodušším případě realizováno formou vnořeného seznamu. Jednotlivé podseznamy obsahují dva prvky: jméno příslušného rozbalovacího menu a druhým prvkem je další podseznam s jednotlivými položkami menu. Hlavní menu s dvojicí rozbalovacích menu může být definováno následovně:
menu = [ ["File", ["New", "Open", "Save", "---", "Exit"]], ["Help", ["About"]], ]
Výsledné okno s hlavním menu může vypadat takto:
Obrázek 15: Okno aplikace s hlavním menu.
Celý zdrojový kód demonstračního příkladu s oknem a hlavním menu:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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.Column([ [sg.Radio("Light", "THEME", default=False, key="light_theme")], [sg.Radio("Dark", "THEME", default=True, key="dark_theme")], ]), ], ] menu = [ ["File", ["New", "Open", "Save", "---", "Exit"]], ["Help", ["About"]], ] layout = [ [sg.Menu(menu)], [ sg.Frame("User", left_column), sg.Frame("Settings", right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #25", 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()
12. Přidání stavového řádku do okna aplikace
Kromě hlavního menu se v aplikacích s grafickým uživatelským rozhraním mnohdy setkáme i s realizací stavového řádku. V knihovně PySimpleGUI je stavový řádek představován GUI komponentou nazvanou StatusBar, která v tom nejjednodušším případě bude obsahovat pouze nějaký text (ten lze později měnit). Typicky bývá stavový řádek umístěn v dolní části okna, tedy například takto:
layout = [ [sg.Menu(menu)], [ sg.Frame("User", left_column), sg.Frame("Settings", right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], [sg.StatusBar("Status bar")], ]
Výsledek bude vypadat takto:
Obrázek 16: Okno aplikace s přidaným stavovým řádkem.
Opět nezapomeneme na úplný zdrojový kód aplikace s oknem, v němž je kromě dalších komponent použit i stavový řádek:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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.Column([ [sg.Radio("Light", "THEME", default=False, key="light_theme")], [sg.Radio("Dark", "THEME", default=True, key="dark_theme")], ]), ], ] menu = [ ["File", ["New", "Open", "Save", "---", "Exit"]], ["Help", ["About"]], ] layout = [ [sg.Menu(menu)], [ sg.Frame("User", left_column), sg.Frame("Settings", right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], [sg.StatusBar("Status bar")], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #26", 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()
13. Vlastní způsob vykreslení titulku okna
Titulek okna (resp. přesněji řečeno oken) lze při použití knihovny PySimpleGUI vykreslit dvěma způsoby. Výchozí způsob využívá vlastnosti okenního manažeru (Window Manager), ovšem pokud při konstrukci okna použijeme parametr use_custom_titlebar nastavený na hodnotu True, bude vlastně vykresleno okno bez standardního titulkového pruhu. Ten bude následně vykreslen přímo v ploše okna knihovnou PySimpleGUI a bude tedy vypadat odlišně:
# vytvoření okna s ovládacími prvky window = sg.Window("Window #27", layout, use_custom_titlebar=True)
Výsledek může vypadat následovně:
Obrázek 17: Vlastní způsob vykreslení titulku okna.
A samozřejmě si ukážeme i úplný zdrojový kód příkladu:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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.Column([ [sg.Radio("Light", "THEME", default=False, key="light_theme")], [sg.Radio("Dark", "THEME", default=True, key="dark_theme")], ]), ], ] menu = [ ["File", ["New", "Open", "Save", "---", "Exit"]], ["Help", ["About"]], ] layout = [ [sg.Menu(menu)], [ sg.Frame("User", left_column), sg.Frame("Settings", right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], [sg.StatusBar("Status bar")], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #27", layout, use_custom_titlebar=True) # 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()
14. Přidání kontextového menu
Další důležitou komponentou, především pro aplikace používané profesionály, je komponenta představující kontextové menu. Samotná definice kontextového menu je poněkud zvláštní, protože se typicky jedná o menu bez „rozbalovacího“ elementu. Proto se mnohdy setkáme s touto definicí:
context_menu = ["", ["About", "---", "Exit"]]
Kontextové menu se do okna aplikace přidá takto:
# vytvoření okna s ovládacími prvky window = sg.Window("Window #28", layout, use_custom_titlebar=False, right_click_menu=context_menu)
Úplný zdrojový kód aplikace s kontextovým menu:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [ sg.Text("Name", size=(8, 0)), sg.InputText(key="name", size=(20, 0)) ], [ sg.Text("Surname", size=(8, 0)), sg.InputText(key="surname", size=(20, 0)) ], ] right_column = [ [ 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.Column([ [sg.Radio("Light", "THEME", default=False, key="light_theme")], [sg.Radio("Dark", "THEME", default=True, key="dark_theme")], ]), ], ] menu = [ ["File", ["New", "Open", "Save", "---", "Exit"]], ["Help", ["About"]], ] layout = [ [sg.Menu(menu)], [ sg.Frame("User", left_column), sg.Frame("Settings", right_column), ], [ sg.Push(), sg.Submit(), sg.Push(), ], [sg.StatusBar("Status bar")], ] context_menu = ["", ["About", "---", "Exit"]] # vytvoření okna s ovládacími prvky window = sg.Window("Window #28", layout, use_custom_titlebar=False, right_click_menu=context_menu) # 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()
15. Kreslicí plátno (canvas)
Poměrně důležitou součástí knihovny PySimpleGUI je podpora kreslení grafických objektů na takzvané kreslicí plátno neboli canvas. Jedná se o techniku, která je do značné míry postavena na knihovně TkInter, v níž je podpora kreslicího plátna velmi sofistikovaná (a vlastně se těžko hledá její přímá obdoba či náhrada v jiných GUI toolkitech). V dalším textu (i v části třetího článku) se budeme tomuto tématu věnovat, protože v některých oblastech může být použití kreslicího plátna velmi užitečné.
16. Přidání kreslicího plátna do okna aplikace
Kreslicí plátno se z pohledu knihovny PySimpleGUI chová jako běžný prvek grafického uživatelského rozhraní. Vytváří se konstruktorem PySimpleGUI.Canvas a – jak uvidíme dále – můžeme při jeho konstrukci předat několik důležitých parametrů. Pokusme se ovšem pro začátek na plochu okna vložit kreslicí plátno vytvořené pouze zavoláním jeho konstruktoru, tj. bez předání dalších parametrů. Okno aplikace rozdělíme na levou a pravou část, přičemž plátno bude umístěno do pravé části:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [sg.Button("Exit", size=(8, 0))], ] right_column = [ [ sg.Canvas(), ], ] layout = [ [ sg.Frame("Commands", left_column), sg.Frame("Canvas", right_column), ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #29", layout, use_custom_titlebar=True) # 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ýsledek by měl vypadat následovně:
Obrázek 18: Kreslicí plátno ve výchozí velikosti přidané na plochu okna.
17. Specifikace velikosti a barvy pozadí kreslicího plátna
U kreslicího plátna mnohdy budeme potřebovat specifikovat jeho rozměry. Na rozdíl od ostatních GUI komponent, jejichž velikosti se specifikují ve znacích (což je ovšem dosti vágní označení, které odpovídá logickým jednotkám „em“ a „x“), se rozměry plátna zadávají přímo v pixelech, což je pro tuto komponentu lepší řešení. A taktéž můžeme přímo specifikovat barvu pozadí plátna. Pro tento účel slouží nepovinný parametr nazvaný background_color:
sg.Canvas(background_color='white', size=(320, 240)),
Výsledek by měl vypadat takto:
Obrázek 19: Kreslicí plátno ve specifikované velikosti a se zadanou barvou pozadí přidané na plochu okna.
Úplný zdrojový kód dnešního posledního demonstračního příkladu vypadá následovně:
import PySimpleGUI as sg # ovládací prvky, které se mají zobrazit v okně left_column = [ [sg.Button("Exit", size=(8, 0))], ] right_column = [ [ sg.Canvas(background_color='white', size=(320, 240)), ], ] layout = [ [ sg.Frame("Commands", left_column), sg.Frame("Canvas", right_column), ], ] # vytvoření okna s ovládacími prvky window = sg.Window("Window #29", layout, use_custom_titlebar=True) # 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()
18. Obsah navazujícího článku
Ve třetím článku o knihovně PySimpleGUI se budeme zabývat převážně tím, jakým způsobem lze využít kreslicí plátno (canvas). Jedná se totiž o důležitou komponentu, která se používá například i pro tvorbu a vykreslení grafů, diagramů, různých složitějších struktur, ale i herního prostředí atd.
19. Repositář s demonstračními příklady
Všechny Pythonovské skripty, které jsme si v minulém i 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:
20. Odkazy na Internetu
- PySimpleGUI
https://www.pysimplegui.org/en/latest/ - Kivy na GitHubu
https://github.com/kivy/kivy - DearPyGui na GitHubu
https://github.com/hoffstadt/DearPyGui - PySimpleGUI Tutorial
https://www.tutorialspoint.com/pysimplegui/index.htm - PySimpleGUI – Canvas Element
https://www.tutorialspoint.com/pysimplegui/pysimplegui_canvas_element.htm - Dokumentace ke knihovně PySimpleGUI
https://www.pysimplegui.org/en/latest/ - Dokumentace ke knihovně DearPyGui
https://dearpygui.readthedocs.io/en/latest/index.html# - 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/ - Stránky projektu wxPython
https://wxpython.org/ - wxPython Project Phoenix (na GitHubu)
https://github.com/wxWidgets/Phoenix/blob/wxPython-4.0.3/README.rst - wxPython API Documentation
https://docs.wxpython.org/index.html - wxWidgets
https://wxwidgets.org/ - wxPython 4.0.3 na PyPi
https://pypi.org/project/wxPython/4.0.3/ - wxGlade – a GUI builder for wxWidgets
http://wxglade.sourceforge.net/ - Repositář projektu wxGlade
https://github.com/wxGlade/wxGlade/ - wxGlade’s documentation
http://wxglade.sourceforge.net/docs/index.html - Graphical User Interfaces (GUI)
https://pythonspot.com/gui/ - wxPyWiki
https://wiki.wxpython.org/FrontPage - Getting started with wxPython
https://wiki.wxpython.org/Getting%20Started#A_First_Application:_.22Hello.2C_World.22 - wxPython GUI tutorial
https://pythonspot.com/wxpython-gui-tutorial/ - wxPython tutorial
http://zetcode.com/wxpython/ - Build wxPython On Raspberry Pi
https://wiki.wxpython.org/BuildWxPythonOnRaspberryPi - wxPython History
https://wxpython.org/pages/history/index.html - Installing wxPython 4.0 (Project Phoenix) on Fedora 27
https://blog.wizardsoftheweb.pro/installing-wxpython-on-fedora/ - Category:Software that uses wxWidgets
https://en.wikipedia.org/wiki/Category:Software_that_uses_wxWidgets - Hra Breakout napísaná v Tkinteri
https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/ - 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/ - Hand Coded GUI Versus Qt Designer GUI
https://stackoverflow.com/questions/387092/hand-coded-gui-versus-qt-designer-gui - Qt Creator Manual
http://doc.qt.io/qtcreator/ - Qt Designer Manual
http://doc.qt.io/qt-5/qtdesigner-manual.html - Qt Creator (Wikipedia)
https://en.wikipedia.org/wiki/Qt_Creator - QIODevice
https://pyside.github.io/docs/pyside/PySide/QtCore/QIODevice.html#PySide.QtCore.QIODevice - QFile
https://pyside.github.io/docs/pyside/PySide/QtCore/QFile.html#PySide.QtCore.QFile - QUiLoader
https://pyside.github.io/docs/pyside/PySide/QtUiTools/QUiLoader.html#PySide.QtUiTools.PySide.QtUiTools.QUiLoader.load - QSvgWidget
https://pyside.github.io/docs/pyside/PySide/QtSvg/QSvgWidget.html - QByteArray
https://pyside.github.io/docs/pyside/PySide/QtCore/QByteArray.html - Differences Between PySide and PyQt
https://wiki.qt.io/Differences_Between_PySide_and_PyQt - PySide 1.2.1 tutorials
https://pyside.github.io/docs/pyside/tutorials/index.html - PySide tutorial
http://zetcode.com/gui/pysidetutorial/ - Drawing in PySide
http://zetcode.com/gui/pysidetutorial/drawing/ - Qt Core
https://pyside.github.io/docs/pyside/PySide/QtCore/Qt.html - Signals & Slots
http://doc.qt.io/qt-4.8/signalsandslots.html - Signals and Slots in PySide
http://wiki.qt.io/Signals_and_Slots_in_PySide - Intro to PySide/PyQt: Basic Widgets and Hello, World!
http://www.pythoncentral.io/intro-to-pysidepyqt-basic-widgets-and-hello-world/ - Leo editor
http://leoeditor.com/ - IPython Qt Console aneb vylepšený pseudoterminál
https://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-ipython-a-ipython-notebook/#k06 - 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