Hlavní navigace

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

3. 10. 2017
Doba čtení: 17 minut

Sdílet

Další knihovna určená pro tvorbu aplikací s GUI v Pythonu se jmenuje appJar. Jejímž primárním cílem je umožnit tvorbu rozhraní s minimálním úsilím a minimálními znalostmi, takže ji je možné použít například při výuce.

Obsah

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

2. Základní informace o knihovně appJar

3. Instalace knihovny appJar

4. První demonstrační příklad – okno s nápisem „Hello world!“

5. Typy widgetů, které knihovna appJar programátorům nabízí

6. Vytvoření okna s několika tlačítky

7. „Přilepení“ tlačítek k okrajům okna

8. Konfigurace umístění tlačítek v dialogu

9. Skupina tlačítek vytvořená jedním příkazem

10. Naprogramování reakce na stisk tlačítek

11. Nastavení základních atributů widgetů

12. Ovládací prvek link

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

14. Odkazy na Internetu

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

V předchozích devíti částech seriálu o tvorbě grafického uživatelského rozhraní v Pythonu jsme si popsali všechny důležité koncepty, na nichž je postavena knihovna Tkinter, která ve skutečnosti tvoří relativně úzké rozhraní mezi interpretrem programovacího jazyka Python a knihovnou Tk. S využitím Tkinteru je možné začít psát plnohodnotné aplikace vybavené grafickým uživatelským rozhraním, a to poměrně rychle a s malými vstupními znalostmi, ovšem na Tkinteru je stále v některých ohledech patrné, že je skutečně „pouze“ rozhraním ke knihovně určené pro jiný programovací jazyk. Příkladem může být například způsob pojmenování událostí, pojmenování základních kláves či specifikace, který znak v položce menu má být podtržený.

Obrázek 1: Knihovna Tkinter je vybavena i univerzálně použitelným widgetem představujícím kreslicí plochu.

2. Základní informace o knihovně appJar

Aby se vývoj aplikací vybavených grafickým uživatelským rozhraním ještě více zjednodušil, byla vytvořena knihovna nazvaná appJar. Tvůrcem této knihovny je Richard Jarvis, který pracuje jako učitel. Richardovým cílem bylo navrhnout appJar takovým způsobem, aby byla programová tvorba grafického uživatelského rozhraní co nejjednodušší a aby tak bylo možné knihovnu appJar použít ve výuce. Tento cíl se skutečně do značné míry podařilo splnit, takže v současnosti představuje appJar s velkou pravděpodobností ten nejrychlejší a současně i nejjednodušší způsob, jakým lze v Pythonu vytvořit aplikaci s grafickým uživatelským rozhraním, i když je nutné poznamenat, že některé pokročilejší ovládací prvky nejsou k dispozici (některé nejsou k dispozici ani v původním Tkinteru, ostatně i proto vznikla rozšiřující knihovna tkinter.tix, jejíž možnosti si popíšeme příště).

Knihovna appJar ovšem navíc obsahuje i další podpůrné moduly, které jsou při tvorbě GUI užitečné. Jedná se především o:

  • Sadu ikon uložených ve formátu PNG, které je možné v aplikacích použít a které jsou uvolněny pod CCPL (Creative Commons Public License). Tyto ikony je možné získat v různých velikostech na adrese http://www.defaulticon.com/.
  • Moduly nazvané png.py a tkinter_png.py, které zajišťují načítání rastrových obrázků ve formátu PNG. To mj. znamená, že aplikace s GUI je možné vyvíjet a spouštět i na těch systémech, kde není nainstalována knihovna PIL. Moduly jsou implementovány v čistém Pythonu, takže není nutné provádět překlad (a tím pádem „bojovat“ s překladačem céčka, jeho knihovnami atd.).
  • Modul nanojpeg.py, který zajišťuje načítání rastrových obrázků ve formátu JPEG. Opět se jedná o modul psaný v čistém Pythonu, takže se v žádném případě nejedná o nejrychlejší implementace dekodéru JPEGu, ale na druhou stranu je tato implementace plně přenositelná (v tom smyslu, že pouze postačuje nakopírovat zdrojové kódy modulu na počítač vybavený interpretrem Pythonu, bez nutnosti instalovat či konfigurovat překladač céčka).
  • Modul TkDND zajišťující v aplikacích funkci „drag and drop“. Jedná se o jediný modul, který vyžaduje nativní knihovny, které jsou součástí instalace appJar.

Obrázek 2: Sada ikon dodávaná společně s knihovnou appJar.

3. Instalace knihovny appJar

Ve skutečnosti není nutné knihovnu appJar složitě instalovat, což je na školách obecně problematické, neboť to vyžaduje koordinaci učitele s administrátorem (samozřejmě je nutné mít na počítači nainstalovaný Python, a to buď Python 2.x nebo 3.x, dokonce ani nejsou vyžadovány poslední verze Pythonu; opět kvůli snadnému použití na školách). Namísto instalace je pouze nutné z projektových stránek umístěných na adrese http://appjar.info/ stáhnout ZIP archiv a ten rozbalit do adresáře s projektem (a popřípadě nastavit .gitignore, aby se vzniklý podadresář neukládal do repositáře vašeho projektu).

Struktura adresáře rozbalené knihovny appJar by měla vypadat zhruba takto:

.
├── appjar.py
├── examples
│   └── showcase.py
├── gpl-3.0.txt
├── __init__.py
├── lib
│   ├── __init__.py
│   ├── license.txt
│   ├── nanojpeg.py
│   ├── png.py
│   ├── README.txt
│   ├── tkdnd2.8
│   │   ├── pkgIndex.tcl
│   │   ├── tcl_files
│   │   │   ├── tkdnd_compat.tcl
│   │   │   ├── tkdnd_generic.tcl
│   │   │   ├── tkdnd_macosx.tcl
│   │   │   ├── tkdnd_unix.tcl
│   │   │   └── tkdnd_windows.tcl
│   │   ├── tcl_libs
│   │   │   ├── libtkdnd2.8_arm.so
│   │   │   ├── libtkdnd2.8.dll
│   │   │   ├── libtkdnd2.8.dylib
│   │   │   ├── libtkdnd2.8_lin32.so
│   │   │   ├── libtkdnd2.8_lin64.so
│   │   │   ├── libtkdnd2.8.so
│   │   │   └── libtkdnd2.8_win64.dll
│   │   └── tkdnd.tcl
│   ├── TkDND_wrapper.py
│   ├── tkinter_png.py
│   └── tooltip.py
└── resources
    └── icons
        ├── 3d-cube.png
        ├── 3d-cylinder.png
        ...
        ...
        ...

Poznámka: povšimněte si, že modul TkDND využívá nativní knihovnu, takže ho bylo nutné přeložit pro všechny (?) běžné architektury. Je to ostatně patrné při pohledu do adresáře appJar/lib/tkdnd2.8/tcl_libs, v němž by se měly nacházet tyto soubory:

libtkdnd2.8_arm.so
libtkdnd2.8.dll
libtkdnd2.8.dylib
libtkdnd2.8_lin32.so
libtkdnd2.8_lin64.so
libtkdnd2.8.so
libtkdnd2.8_win64.dll

4. První demonstrační příklad – okno s nápisem „Hello world!“

Před podrobnějším popisem vlastností knihovny appJar si ukažme velmi jednoduchý demonstrační příklad, v němž se vytvoří okno obsahující textové návěští s textem „Hello world!“. Pokud nebudeme počítat první řádek, který vlastně není zcela zapotřebí (záleží na tom, jak se bude projekt spouštět), bude mít celý příklad pouhé čtyři textové řádky, což je méně, než v případě přímého použití knihovny Tkinter:

#!/usr/bin/env python
 
from appJar import gui
 
app = gui()
 
app.addLabel("title", "Hello world!")
 
app.go()

Obrázek 3: Takto vypadá dnešní první demonstrační příklad po spuštění.

Poznámka: úvodní řádek se shebangem je možné vynechat, pokud se bude skript spouštět přes interpret Pythonu.

První skutečný řádek programu načte z modulu appJar deklaraci třídy gui:

from appJar import gui

Tato třída skutečně reprezentuje základní prvek grafického uživatelského rozhraní. Zjednodušeně řečeno si můžeme instanci této třídy představit jako hlavní okno aplikace, do něhož můžeme vkládat widgety, vytvářet přes něj další podokna (sub windows) a spouštět smyčku obsluhy událostí. Vytvoření hlavního okna aplikace je triviální:

app = gui()

Na třetím řádku přidáme do hlavního okna aplikace textové návěští. Povšimněte si, že při vytváření návěští zadáváme takzvaný titulek (title) představující jméno návěští a samozřejmě také text, který se má zobrazit uživateli:

app.addLabel("title", "Hello world!")

Na posledním řádku spustíme obsluhu smyčky událostí, a to metodou nazvanou go. Implicitně se této metodě předává pouze self, v případě potřeby je však možné specifikovat jazyk GUI:

app.go()

Poznámka: tato metoda by se měla volat po inicializaci všech prvků GUI. Současně se jedná o poslední explicitně zavolaný příkaz v aplikace – ostatní volání zajistí handler smyčky událostí.

Pro porovnání si ukažme, jak by se podobný příklad implementoval přímo s použitím Tkinteru. V tomto případě musíme explicitně vytvořit nové okno (root), vytvořit návěští, vložit ho do okna a zavolat smyčku obsluhy událostí:

#!/usr/bin/env python
 
from tkinter import *
 
root = Tk()
 
label = Label(root, text="Hello world!")
 
label.pack()
 
root.mainloop()

5. Typy widgetů, které knihovna appJar programátorům nabízí

Knihovna appJar nabízí vývojářům poměrně velké množství widgetů. Některé widgety jsou interně značně komplikované (příkladem může být DatePicker a Properties), ovšem programové ovládání těchto widgetů je ve skutečnosti velmi snadné – většina widgetů pouze na základě uživatelského vstupu nastaví hodnotu specifikovaného atributu. V následující tabulce jsou všechny podporované widgety vypsány:

Jméno widgetu Stručný popis
Label textové návěští neměnitelné uživatelem
Message několikařádkové textové návěští
   
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
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ů

Poznámka: povšimněte si, že widgety typu rozbalovací strom či tabulka (prozatím) nejsou podporovány, což může znepříjemnit vývoj aplikací se složitějším GUI.

6. Vytvoření okna s několika tlačítky

Nejjednodušším aktivním widgetem jsou tlačítka (Button), takže si nějaká přidejme do našeho demonstračního projektu. Zatímco návěští se přidávala metodou addLabel(), u tlačítek se používá metoda addButton(). Této metodě se předávají dva parametry – text zobrazený na tlačítku a reference na callback funkci, která se zavolá při stisku tlačítka. Pokud namísto reference předáme hodnotu None, nebude tlačítko na stisk reagovat (resp. vizuálně se „zamáčkne“, ale nic dalšího se nestane):

#!/usr/bin/env python
 
from appJar import gui
 
app = gui()
 
app.addLabel("title", "Hello world!")
 
app.addButton("Ok", None)
app.addButton("Quit", None)
 
app.go()

Obrázek 4: Screenshot druhého demonstračního příkladu.

Existují i další varianty tlačítka, především tlačítko s ikonou a tlačítko s libovolným obrázkem. Tento typ tlačítek si ukážeme příště.

7. „Přilepení“ tlačítek k okrajům okna

Widgety se do okna umisťují automaticky do neviditelné mřížky (grid), ovšem jejich velikost i relativní pozici je samozřejmě možné upravovat. K tomu slouží několik metod třídy gui, které nastavují konfiguraci platnou pro všechny dále vytvářené widgety:

Metoda Význam
setSticky() přilepení widgetů k okraji buněk
setStretch() řídí chování widgetů při změně velikosti okna
setExpand() interně má stejný význam jako setStretch()
setPadX() mezery mezi buňkami umístěnými vedle sebe
setPadY() mezery mezi buňkami umístěnými nad sebou
setPadding() kombinace předchozích dvou metod

Nejužitečnější je metoda setSticky(), která určuje, ke kterému okraji buňky má být widget „přilepen“. Možné jsou kombinace znaků N, S, W, E (podle světových stran, podobně jako v knihovně Tkinter). V dalším příkladu je specifikováno, aby se všechny widgety přilepily k západnímu (levému) i východnímu (pravému) okraji buňky, což znamená, že tlačítka budou při změně velikosti okna zvětšována a zmenšována a navíc budou mít i stejnou šířku:

#!/usr/bin/env python
 
from appJar import gui
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!")
 
app.addButton("Ok", None)
app.addButton("Quit", None)
 
app.go()

Obrázek 5: Screenshot třetího demonstračního příkladu.

Poznámka: volání metody setSticky() ovlivní chování všech dále vytvořených widgetů, nejedná se tedy o globální konfiguraci.

8. Konfigurace umístění tlačítek v dialogu

Ve skutečnosti mají metody pro vytvoření widgetů čtveřici nepovinných (pojmenovaných) parametrů sloužících k určení, do jaké buňky mřížky má být widget vložen a kolik buněk zabere:

row=None, column=0, colspan=0, rowspan=0

Implicitně jsou widgety umisťovány pod sebe (row=None, column=0), ale to je samozřejmě možné změnit specifikací parametrů row a column:

#!/usr/bin/env python
 
from appJar import gui
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addButton("Ok", None, 1, 0)
app.addButton("Quit", None, 1, 1)
 
app.go()

Alternativně je možné nepovinné parametry při volání pojmenovat, což je čitelnější, protože si nemusíte pamatovat pořadí parametrů:

#!/usr/bin/env python
 
from appJar import gui
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addButton("Ok", None, row=1, column=0)
app.addButton("Quit", None, row=1, column=1)
 
app.go()

Obrázek 6: Screenshot čtvrtého demonstračního příkladu.

9. Skupina tlačítek vytvořená jedním příkazem

Poměrně často se setkáme s nutností vložit do okna větší množství tlačítek umístěných vedle sebe. K tomuto účelu je možné použít metodu addButtons(), které se předá seznam jmen tlačítek a dále reference na callback funkci, která se má zavolat při stisku jakéhokoli tlačítka ve skupině. Alternativně lze předat seznam callback funkcí, potom bude po stisku každého tlačítka zavolána odpovídající callback funkce. Případné další nepovinné parametry jsou shodné s metodou addButton():

#!/usr/bin/env python
 
from appJar import gui
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addButtons(["Ok", "Quit"], None, 1, 0)
 
app.go()

Obrázek 7: Screenshot pátého demonstračního příkladu.

10. Naprogramování reakce na stisk tlačítek

Tlačítka v aplikacích samozřejmě neslouží jen pro potěchu oka; naopak musí nějakým způsobem reagovat na akce prováděné uživatelem. K tomu slouží callback funkce, jejichž jméno se zadává při vkládání tlačítek do okna:

app.addButton("Ok", onButtonPress)

Podobně je možné specifikovat callback funkci pro skupinu tlačítek:

app.addButtons(["Ok", "Quit"], onButtonPress, 1, 0)

V případě, že dojde ke stisku nějakého tlačítka, je callback funkce zavolána a do jejího (jediného) parametru se předá text na tlačítku. To znamená, že pokud je jedna callback funkce použita pro obsluhu většího množství tlačítek, můžeme na základě předaného parametru rozhodnout, o jaké tlačítko se jednalo. V následující callback funkci je rozhodování jednoduché:

def onButtonPress(buttonName):
    if buttonName == "Quit":
        app.stop()
    else:
        app.infoBox("Ok, Ok", "Ok button pressed")

Úplný zdrojový kód příkladu, v němž je použita výše popsaná callback funkce, vypadá následovně:

#!/usr/bin/env python
 
from appJar import gui
 
 
def onButtonPress(buttonName):
    if buttonName == "Quit":
        app.stop()
    else:
        app.infoBox("Ok, Ok", "Ok button pressed")
 
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addButtons(["Ok", "Quit"], onButtonPress, 1, 0)
 
app.go()

Obrázek 8: Screenshot šestého demonstračního příkladu.

Ve skutečných aplikacích bývá výhodnější reagovat na stisk každého tlačítka v samostatné callback funkci:

#!/usr/bin/env python
 
from appJar import gui
 
 
def onQuitButtonPress(buttonName):
    app.stop()
 
 
def onOkButtonPress(buttonName):
    app.infoBox("Ok, Ok", "Ok button pressed")
 
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addButtons(["Ok", "Quit"], [onOkButtonPress, onQuitButtonPress], 1, 0)
 
app.go()

11. Nastavení základních atributů widgetů

U widgetů je možné do jisté míry nastavovat i jejich vzhled. Příkladem mohou být textová návěští, u nichž lze nastavit jejich pozadí, a to konkrétně metodou setLabelBg(). Prvním parametrem této metody je titulek návěští, dalším parametrem pak barva. Ta se specifikuje buď jménem nebo hexa trojicí #rrggbb, podobně jako v knihovně Tkinter, na HTML stránkách či v CSS:

app.addLabel("redLabel", "Red")
app.setLabelBg("redLabel", "red")

Podívejme se nyní na příklad, v němž je vytvořeno pět návěští, každé s jinou barvou pozadí:

#!/usr/bin/env python
 
from appJar import gui
 
 
def onButtonPress(buttonName):
    app.stop()
 
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addLabel("redLabel", "Red")
app.addLabel("orangeLabel", "Orange")
app.addLabel("yellowLabel", "Yellow")
app.addLabel("greenLabel", "Green")
app.addLabel("blueLabel", "Blue")
 
app.setLabelBg("redLabel", "red")
app.setLabelBg("orangeLabel", "orange")
app.setLabelBg("yellowLabel", "yellow")
app.setLabelBg("greenLabel", "green")
app.setLabelBg("blueLabel", "blue")
 
app.addButton("Quit", onButtonPress)
 
app.go()

Obrázek 9: Screenshot sedmého demonstračního příkladu.

Pokud preferujete použití trojice barvových složen v šestnáctkové soustavě, není nic jednoduššího:

#!/usr/bin/env python
 
from appJar import gui
 
 
def onButtonPress(buttonName):
    app.stop()
 
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addLabel("redLabel", "Red")
app.addLabel("orangeLabel", "Orange")
app.addLabel("yellowLabel", "Yellow")
app.addLabel("greenLabel", "Green")
app.addLabel("blueLabel", "Blue")
 
app.setLabelBg("redLabel", "#ff0000")
app.setLabelBg("orangeLabel", "#ff8000")
app.setLabelBg("yellowLabel", "#ffff00")
app.setLabelBg("greenLabel", "#ff00ff")
app.setLabelBg("blueLabel", "#0000ff")
 
app.addButton("Quit", onButtonPress)
 
app.go()

Lze použít i zkrácený zápis hexa tripletu:

#!/usr/bin/env python
 
from appJar import gui
 
 
def onButtonPress(buttonName):
    app.stop()
 
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addLabel("redLabel", "Red")
app.addLabel("orangeLabel", "Orange")
app.addLabel("yellowLabel", "Yellow")
app.addLabel("greenLabel", "Green")
app.addLabel("blueLabel", "Blue")
 
app.setLabelBg("redLabel", "#f00")
app.setLabelBg("orangeLabel", "#f80")
app.setLabelBg("yellowLabel", "#ff0")
app.setLabelBg("greenLabel", "#0f0")
app.setLabelBg("blueLabel", "#00f")
 
app.addButton("Quit", onButtonPress)
 
app.go()

12. Ovládací prvek link

Widget Link, který se do okna přidává s využitím metody addLink(), se svým chováním podobá tlačítkům, protože taktéž reaguje na kliknutí myší popř. na stisk tlačítka pomocí klávesnice (přesunutí fokusu + použití mezerníku). Vizuálně ovšem widget Link skutečně připomíná hypertextový odkaz používaný na webových stránkách, což je ostatně patrné z tohoto příkladu:

#!/usr/bin/env python
 
from appJar import gui
 
 
def onLinkClick(link):
    print(link)
    app.stop()
 
 
app = gui()
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addLink("Quit", onLinkClick)
 
app.go()

Obrázek 10: Okno s odkazem – widgetem Link.

Podívejme se na složitější příklad, který kombinuje odkaz (link) s textovými návěštími, u nichž se změnila barva pozadí:

#!/usr/bin/env python
 
from appJar import gui
 
 
def onLinkClick(link):
    print(link)
    app.stop()
 
 
app = gui()
 
app.setSticky("we")
 
app.addLabel("title", "Hello world!", colspan=2)
 
app.addLabel("redLabel", "Red")
app.addLabel("orangeLabel", "Orange")
app.addLabel("yellowLabel", "Yellow")
app.addLabel("greenLabel", "Green")
app.addLabel("blueLabel", "Blue")
 
app.setLabelBg("redLabel", "red")
app.setLabelBg("orangeLabel", "orange")
app.setLabelBg("yellowLabel", "yellow")
app.setLabelBg("greenLabel", "green")
app.setLabelBg("blueLabel", "blue")
 
app.addLink("Quit", onLinkClick)
 
app.go()

Obrázek 11: Screenshot osmého demonstračního příkladu.

root_podpora

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

Zdrojové kódy všech osmi 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í adresáři rozbalenou knihovnu appJar!

14. Odkazy na Internetu

  1. Hra Breakout napísaná v Tkinteri
    https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/
  2. Hra Snake naprogramovaná v Pythone s pomocou Tkinter
    https://www.root.cz/clanky/hra-snake-naprogramovana-v-pythone-s-pomocou-tkinter/
  3. TkDND
    http://freecode.com/projects/tkdnd
  4. Python Tkinter Fonts
    https://www.tutorialspoin­t.com/python/tk_fonts.htm
  5. The Tkinter Canvas Widget
    http://effbot.org/tkinter­book/canvas.htm
  6. Ovládací prvek (Wikipedia)
    https://cs.wikipedia.org/wi­ki/Ovl%C3%A1dac%C3%AD_prvek_­%28po%C4%8D%C3%ADta%C4%8D%29
  7. Rezervovaná klíčová slova v Pythonu
    https://docs.python.org/3/re­ference/lexical_analysis.html#ke­ywords
  8. TkDocs: Styles and Themes
    http://www.tkdocs.com/tuto­rial/styles.html
  9. Drawing in Tkinter
    http://zetcode.com/gui/tkin­ter/drawing/
  10. Changing ttk widget text color (StackOverflow)
    https://stackoverflow.com/qu­estions/16240477/changing-ttk-widget-text-color
  11. The Hitchhiker's Guide to Pyhton: GUI Applications
    http://docs.python-guide.org/en/latest/scenarios/gui/
  12. 7 Top Python GUI Frameworks for 2017
    http://insights.dice.com/2014/11/26/5-top-python-guis-for-2015/
  13. GUI Programming in Python
    https://wiki.python.org/mo­in/GuiProgramming
  14. Cameron Laird's personal notes on Python GUIs
    http://phaseit.net/claird/com­p.lang.python/python_GUI.html
  15. Python GUI development
    http://pythoncentral.io/introduction-python-gui-development/
  16. Graphic User Interface FAQ
    https://docs.python.org/2/faq/gu­i.html#graphic-user-interface-faq
  17. TkInter
    https://wiki.python.org/moin/TkInter
  18. Tkinter 8.5 reference: a GUI for Python
    http://infohost.nmt.edu/tcc/hel­p/pubs/tkinter/web/index.html
  19. TkInter (Wikipedia)
    https://en.wikipedia.org/wiki/Tkinter
  20. appJar
    http://appjar.info/
  21. appJar (Wikipedia)
    https://en.wikipedia.org/wiki/AppJar
  22. appJar na Pythonhosted
    http://pythonhosted.org/appJar/
  23. appJar widgets
    http://appjar.info/pythonWidgets/
  24. Stránky projektu PyGTK
    http://www.pygtk.org/
  25. PyGTK (Wikipedia)
    https://cs.wikipedia.org/wiki/PyGTK
  26. Stránky projektu PyGObject
    https://wiki.gnome.org/Pro­jects/PyGObject
  27. Stránky projektu Kivy
    https://kivy.org/#home
  28. Stránky projektu PyQt
    https://riverbankcomputin­g.com/software/pyqt/intro
  29. PyQt (Wikipedia)
    https://cs.wikipedia.org/wiki/PyGTK
  30. Stránky projektu PySide
    https://wiki.qt.io/PySide
  31. PySide (Wikipedia)
    https://en.wikipedia.org/wiki/PySide
  32. Stránky projektu Kivy
    https://kivy.org/#home
  33. Kivy (framework, Wikipedia)
    https://en.wikipedia.org/wi­ki/Kivy_(framework)
  34. QML Applications
    http://doc.qt.io/qt-5/qmlapplications.html
  35. KDE
    https://www.kde.org/
  36. Qt
    https://www.qt.io/
  37. GNOME
    https://en.wikipedia.org/wiki/GNOME
  38. Category:Software that uses PyGTK
    https://en.wikipedia.org/wi­ki/Category:Software_that_u­ses_PyGTK
  39. Category:Software that uses PyGObject
    https://en.wikipedia.org/wi­ki/Category:Software_that_u­ses_PyGObject
  40. Category:Software that uses wxWidgets
    https://en.wikipedia.org/wi­ki/Category:Software_that_u­ses_wxWidgets
  41. GIO
    https://developer.gnome.or­g/gio/stable/
  42. GStreamer
    https://gstreamer.freedesktop.org/
  43. GStreamer (Wikipedia)
    https://en.wikipedia.org/wi­ki/GStreamer
  44. Wax Gui Toolkit
    https://wiki.python.org/moin/Wax
  45. Python Imaging Library (PIL)
    http://infohost.nmt.edu/tcc/hel­p/pubs/pil/
  46. 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/

Byl pro vás článek přínosný?