Hlavní navigace

Použití UI souborů s popisem formulářů ve frameworku PySide

Pavel Tišnovský

V již dvacátém článku o frameworku PySide si ukážeme, jak je možné použít takzvané UI soubory, které obsahují deklarativní popis formulářů či ovládacích prvků (widgetů). Tyto soubory je možné vytvářet například v Qt Creatoru.

Doba čtení: 28 minut

11. Získání referencí na jednotlivé ovládací prvky ve formuláři

12. Demonstrační příklad – navázání akcí (funkcí) na tlačítka ve formuláři

13. Alternativní cesta – vygenerování Pythonovského modulu z deklarativního zápisu formuláře

14. Instalace balíčku pyside-tools s nástrojem pyside-uic

15. Vytvoření modulu s formulářem z jeho deklarativního popisu

16. Přidání kódu pro zobrazení formuláře

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

18. Odkazy na Internetu

1. Použití UI souborů s popisem formulářů ve frameworku PySide

Ve všech předchozích částech tohoto seriálu jsme se zabývali popisem tvorby aplikací s grafickým uživatelským rozhraním, přičemž GUI bylo vždy naprogramováno přímo v Pythonu. Tento postup, kdy se postupně konstruují jednotlivé ovládací prvky, které se posléze vkládají do oken a formulářů, sice v některých případech má své opodstatnění, ovšem samotná tvorba formulářů a především jejich následné úpravy jsou mnohdy komplikované a časově náročné. Jednodušší může být odlišný postup, který se prosadil už kdysi dávno v Delphi a podobných nástrojích – jednotlivé formuláře jsou deklarativně popsány ve vhodném doménově specifickém jazyku a při běhu aplikace jsou tyto deklarace načítány a na základě nich se vytváří skutečné interní struktury, které formuláře popisují. Pro PySide založeném na frameworku Qt se používají tzv. UI soubory popř. QML (Qt Modeling Language). Dnes si popíšeme především práci se soubory UI.

Obrázek 1: Příkladem složitější aplikace s GUI je integrované vývojové prostředí Eric.

2. Soubory UI

Do souborů UI se ukládají popisy jednotlivých uživatelsky definovaných ovládacích prvků (widgetů), formulářů i celých oken. Jedná se o formát založený na XML, což znamená, že tyto soubory je možné relativně snadno zpracovat i dalšími nástroji (XML editory atd.). Tyto soubory lze vytvářet například Qt Creatorem, což je téma, kterému se ve stručnosti budeme věnovat v navazující kapitole. Ve chvíli, kdy je soubor UI s popisem nějakého prvku GUI (widget, formulář, okno) vytvořen, dá se použít několika různými způsoby:

  • Soubor UI lze načíst do běžící aplikace naprogramované v C++ s využitím třídy QUiLoader.
  • Soubor UI lze načíst do běžící aplikace naprogramované v Pythonu, opět s využitím třídy QUiLoader.
  • Soubor UI je možné konvertovat na zdrojový kód v C++ nástrojemUIC (User Interface Compiler).
  • Soubor UI je možné konvertovat na zdrojový kód v Pythonu nástrojemPython-uic. Výsledek by měl být dobře pochopitelný, protože se používají postupy, které jsme si popsali v předchozích článcích.

Dnes nás bude zajímat druhý a čtvrtý bod z předchozího seznamu.

Obrázek 2: Takto vypadá soubor UI otevřený v Qt Creatoru.

3. Použití nástroje Qt Creator pro interaktivní tvorbu formulářů

Jedním z nástrojů, který dokáže vytvářet soubory .ui, je aplikace nazvaná Qt Creator. Jak již název tohoto nástroje napovídá, jedná se o IDE určené primárně pro desktopové prostředí KDE založené na knihovně Qt, ovšem ve skutečnosti nám samozřejmě nic nebrání použít Qt Creator i na desktopu se spuštěným Gnome Shellem popř. nějakým „alternativním“ desktopovým prostředím (jediným problémem bude delší čas spouštění zapříčiněný načítáním knihovny Qt do paměti). To, že je Qt Creator původně orientován na vývoj aplikací postavených na knihovně Qt a tím pádem i na programovacím jazyku C++, je patrné již při pohledu na první screenshoty, kde jsou ukázány dialogy zobrazené při vytváření nového projektu.

Poznámka: dříve (před Qt 5) existovala samostatná aplikace nazvaná Qt Designer, která byla určená prakticky výhradně na návrh GUI. Dnes jsou funkce obou nástrojů sjednoceny právě v Qt Creatoru, i když se například ve starší dokumentaci stále setkáme s původním názvem.

Obrázek 3: Vítací obrazovka dnes již poněkud starší verze Qt Creatoru.

Qt Creator nám při vytváření nových projektů nabízí projekty založené na nějaké existující (předpřipravené) šabloně. V případě Qt Creatoru ovšem většina šablon předpokládá, že je v systému nainstalován nástroj qmake, buď pro Qt verze 4 nebo/i pro Qt verze 5 (je poměrně běžné, že jsou současně nainstalovány obě varianty). Nicméně i pokud se nějaký projekt založí na existující „Qt šabloně“, není nijak problematické změnit jeho nastavení takovým způsobem, aby se namísto qmake používal klasický nástroj make či jiná aplikace zavolaná pro překlad a následné sestavení projektu. Alternativně je možné projekty vytvořit ze zdrojových souborů uložených v systémech pro správu verzi. Podporovány jsou například systémy GIT, CVS, SVN či Mercurial.

Poznámka: nás sice bude v dnešním článku zajímat především návrh formulářů, ovšem aby bylo možné vytvořit nový projekt, je nutné, aby Qt Creator našel qmake. V opačném případě se při pokusu o vytvoření nového projektu vypíše poněkud kryptické hlášení „No valid kits found“.

Obrázek 4: Součástí Qt Creatoru jsou i různé tutoriály.

Pro programátory, kteří jsou zvyklí používat textový editor Vim, může být taktéž užitečná další vlastnost programátorského textového editoru, jenž je součástí Qt Creatoru. Editor totiž dokáže do jisté míry emulovat chování Vimu, samozřejmě včetně jeho multimodálního rozhraní, a dokonce je možné Qt Creator nastavit takovým způsobem, že si přečte uživatelský konfigurační soubor .vimrc. Pokud je režim emulování editoru Vim (takzvaný FakeVim) povolen, je v pravém dolním rohu stavové řádky zobrazen aktuální režim Vimu (COMMAND, INSERT, REPLACE, VISUAL) a s využitím znaku : (dvojtečka) lze přejít do režimu zadávání příkazů, z nichž nejpoužívanější pravděpodobně bude příkaz pro textovou substituci (:s). Režim emulace Vimu lze kdykoli zapnout či vypnout klávesovou zkratkou Alt+V, Alt+V (nejedná se o chybu, skutečně je nutné dvakrát stlačit Alt+V).

Obrázek 5: Jednou ze zajímavých a pro mnohé programátory i užitečných vlastností Qt Creatoru je i režim integrovaného programátorského editoru, který do značné míry napodobuje chování Vimu.

4. Vytvoření deklarace hlavního okna

Qt Creatoru je možné poměrně jednoduše vytvořit design hlavního okna a uložit ho do UI souboru. Nejprve je nutné vytvořit nový projekt, zvolit jeho typ (projekt psaný v C++ a využívající Qt – Qt Widgets Application), zvolit takzvaný kit (Desktop) a konečně specifikovat popř. upravit jméno třídy s implementací chování hlavního okna, jméno UI souboru s designem okna atd.:

Obrázek 6: Dialog, ze kterého je možné vytvořit nový projekt.

V případě, že se při zakládání projektu vypíše hlášení „No valid kits found“ zmíněné již v předchozí kapitole, zkontrolujte v nastavení Qt Creatoru, že byla nalezena vývojová varianta knihovny Qt – viz další screenshot s vyznačením list boxu, který je nutné zkontrolovat:

Obrázek 7: Nastavení prostředí Qt Creatoru s vyznačením list boxu s nalezenou (či nenalezenou) verzí knihovny Qt.

Po úspěšném vytvoření projektu by mělo prostředí Qt Creatoru zobrazit strukturu projektu (nebo většího množství projektů):

Obrázek 8: Struktura nově vytvořeného projektu.

Nyní je již možné výběrem souboru mainwindow.ui otevřít návrhář GUI:

Obrázek 9: Návrhář GUI.

Prozatím nebudeme návrh okna měnit, pouze se podíváme na výslednou verzi souboru https://github.com/tisnik/pre­sentations/blob/master/Pyt­hon_GUI/PySide/mainwindow­.ui. Tu totiž použijeme v demonstračních příkladech:

<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow" >
  <property name="geometry" >
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle" >
   <string>MainWindow</string>
  </property>
  <widget class="QMenuBar" name="menuBar" />
  <widget class="QToolBar" name="mainToolBar" />
  <widget class="QWidget" name="centralWidget" />
  <widget class="QStatusBar" name="statusBar" />
 </widget>
 <layoutDefault spacing="6" margin="11" />
 <pixmapfunction></pixmapfunction>
 <resources/>
 <connections/>
</ui>

5. Načtení deklarace do aplikace naprogramované v Pythonu

Ve chvíli, kdy máme soubor mainwindow.ui k dispozici, můžeme zbytek projektu ignorovat (ostatně je psaný v C++) a využít tento soubor v Pythonu a PySide. Podívejme se, jakým způsobem je možné tento soubor načíst a použít pro vytvoření hlavního okna. O načtení a zpracování UI souborů se stará třída QUiLoader z modulu QtUiTools, která obsahuje metodu load, jíž je možné předat jméno UI souboru (řetězec nebo Unicode řetězec):

def load_ui_form(filename):
    ui_loader = QtUiTools.QUiLoader()
    form = ui_loader.load(filename)
    return form

Výše uvedená funkce vrací referenci na plnohodnotný objekt představující hlavní okno aplikace. Zobrazení takového okna je již velmi snadné, protože celý postup známe z předchozích částí seriálu:

def main():
    QtGui.QApplication.setStyle("plastique")
    app = QtGui.QApplication(sys.argv)
    mainWindow = load_ui_form("mainwindow.ui")
    mainWindow.show()
    sys.exit(app.exec_())

Po spuštění skriptu se skutečně zobrazí okno s prázdným menu a prázdným stavovým řádkem:

Obrázek 10: Výsledná aplikace používající okno deklarované v UI souboru.

Následuje výpis celého zdrojového kódu tohoto příkladu:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
# import "jádra" frameworku Qt i modulu pro GUI
from PySide import QtCore
from PySide import QtGui
 
# třída pro načtení formuláře
from PySide import QtUiTools
 
import sys
 
 
def load_ui_form(filename):
    ui_loader = QtUiTools.QUiLoader()
    form = ui_loader.load(filename)
    return form
 
 
def main():
    QtGui.QApplication.setStyle("plastique")
    app = QtGui.QApplication(sys.argv)
    mainWindow = load_ui_form("mainwindow.ui")
    mainWindow.show()
    sys.exit(app.exec_())
 
 
if __name__ == "__main__":
    main()

6. Alternativní způsob načtení deklarace okna či formuláře s využitím QIODevice

V praxi se můžeme setkat ještě s jedním způsobem načtení deklarace okna nebo formuláře. Tento způsob využívá třídu QIODevice a QFile. Celé načtení je nepatrně složitější:

def load_ui_form(filename):
    ui_loader = QtUiTools.QUiLoader()
    q_file = QtCore.QFile(filename)
    q_file.open(QtCore.QFile.ReadOnly)
    form = ui_loader.load(q_file)
    q_file.close()
    return form

Proč by ale někdo volil tento složitější způsob, u něhož je navíc zapotřebí hlídat uzavření pomocí QFile.close()? Jeho výhoda spočívá v tom, že QIODevice může reprezentovat i různé virtuální souborové systémy, například ZIP archivy, zašifrované soubory, atd. Jen pro úplnost si ukažme, jak bude vypadat upravený příklad, který tento postup využívá:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
# import "jádra" frameworku Qt i modulu pro GUI
from PySide import QtCore
from PySide import QtGui
 
# třída pro načtení formuláře
from PySide import QtUiTools
 
import sys
 
 
def load_ui_form(filename):
    ui_loader = QtUiTools.QUiLoader()
    q_file = QtCore.QFile(filename)
    q_file.open(QtCore.QFile.ReadOnly)
    form = ui_loader.load(q_file)
    q_file.close()
    return form
 
 
def main():
    QtGui.QApplication.setStyle("plastique")
    app = QtGui.QApplication(sys.argv)
    mainWindow = load_ui_form("mainwindow.ui")
    mainWindow.show()
    sys.exit(app.exec_())
 
 
if __name__ == "__main__":
    main()

7. Adresář s dalšími zdroji (ikony atd.)

V případě, že se kromě vlastního UI souboru ve formuláři používají další zdroje, typicky ikony, je nutné vědět popř. nastavit, ve kterém adresáři se mají tyto soubory hledat. Pro tento účel obsahuje třída QUiLoader metody workingDirectory() a setWorkingDirectory(), přičemž první metoda pracuje jako getter a druhá jako setter. Po zavolání QUiLoader.workingDirectory() získáme instanci třídy QDir, která nabízí různé pomocné metody, například path(), canonicalPath() a absolutePath(). Ukažme si použití této třídy na jednoduchém příkladu:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
# import "jádra" frameworku Qt i modulu pro GUI
from PySide import QtCore
from PySide import QtGui
 
# třída pro načtení formuláře
from PySide import QtUiTools
 
import sys
 
 
def main():
    app = QtGui.QApplication(sys.argv)
    ui_loader = QtUiTools.QUiLoader()
    working_directory = ui_loader.workingDirectory()
    print(working_directory.path())
    print(working_directory.absolutePath())
    sys.exit(0)
 
 
if __name__ == "__main__":
    main()

Po spuštění získáme například následující dva řádky (druhý řádek se samozřejmě bude na vašem počítači lišit):

.
/home/tester/presentations/Python_GUI/PySide

8. Vytvoření formuláře v Qt Creatoru

V dalším kroku si již v Qt Creatoru vytvoříme poněkud složitější formulář, který bude obsahovat dvojici tlačítek. Na tato tlačítka následně navážeme callback funkce.

Vytvoříme nový projekt, ovšem bez hlavního okna:

Obrázek 11: Formulář pro vytvoření nového projektu.

Dále do projektu přidáme nový formulář, přičemž opět musíme vybrat šablonu. V tomto případě máme více možností – buď zvolit šablonu s předpřipraveným formulářem nebo nejprve použít prázdný formulář, do které tlačítka vložíme ručně:

Obrázek 12: Výběr šablony pro GUI okno nebo formulář aplikace.

Takto vypadá návrhář formulářů ve chvíli, kdy jsme vybrali již předpřipravenou šablonu. Vidíme, že formulář je založen na třídě QDialog:

Obrázek 13: Interaktivní editor a návrhář GUI s předpřipraveným formulářem.

Podle mého názoru je lepší si formulář vytvořit ručně. Tentokrát bude základ formuláře založený na třídě QWidget, do které vložíme dvě tlačítka typu QPushButton. Navíc je však nutné určit, jakým způsobem budou tlačítka rozmístěna. K tomu slouží správce geometrie (layout manager). Vybereme obě tlačítka a v kontextovém menu zvolíme, že mají být na formulář rozmístěna s využitím správce geometrie QVBoxLayout:

Obrázek 14: Dvojice tlačítek vložených na QWidget s využitím správce geometrie QVBoxLayout.

Následně tlačítka přejmenujeme na helloButton a quitButton. Po přepnutí do textového pohledu na deklaraci formuláře by měl výsledek vypadat zhruba takto:

Obrázek 15: Výsledná podoba deklarace formuláře.

9. Soubor obsahující deklarativní popis formuláře

Výsledkem našeho předchozího snažení by měl být soubor form.ui s následujícím obsahem:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>271</width>
    <height>89</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QHBoxLayout" name="horizontalLayout">
   <item>
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QPushButton" name="helloButton">
       <property name="text">
        <string>Hello!</string>
       </property>
       <property name="default">
        <bool>true</bool>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="quitButton">
       <property name="text">
        <string>Quit</string>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

10. Načtení a použití nového formuláře

Soubor form.ui načteme a zpracujeme naprosto stejným způsobem, jaký jsme již použili v prvním demonstračním příkladu:

  1. Vytvoříme instanci QUiLoader
  2. Načteme deklaraci formuláře metodou load()
  3. Získáme objekt představující formulář; ten zobrazíme metodou show()

Celý postup je jasně patrný ze zdrojového kódu dalšího demonstračního příkladu:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
# import "jádra" frameworku Qt i modulu pro GUI
from PySide import QtCore
from PySide import QtGui
 
# třída pro načtení formuláře
from PySide import QtUiTools
 
import sys
 
 
def load_ui_form(filename):
    ui_loader = QtUiTools.QUiLoader()
    return ui_loader.load(filename)
    return form
 
 
def main():
    QtGui.QApplication.setStyle("plastique")
    app = QtGui.QApplication(sys.argv)
    mainWindow = load_ui_form("form.ui")
    print(mainWindow)
 
    mainWindow.show()
    sys.exit(app.exec_())
 
 
if __name__ == "__main__":
    main()

11. Získání referencí na jednotlivé ovládací prvky ve formuláři

Prozatím umíme zobrazit jen neaktivní okno nebo dialog, protože výběr jednotlivých prvků nemá žádnou odezvu v chování aplikace. Aby bylo možné na jednotlivé prvky GUI navázat callback funkce nebo metody, musíme dokázat získat reference na jednotlivé prvky. K tomu slouží metoda findChild, které se předá typ prvku a jeho jméno. Právě z tohoto důvodu je vhodné prvky v Qt Creatoru vhodně pojmenovat a nenechávat výchozí nicneříkající názvy. Pokud například budeme chtít získat referenci na tlačítko pojmenované „helloButton“, použijeme kód:

btn = mainWindow.findChild(QtGui.QPushButton, "helloButton")

Popř. si připravíme pomocnou funkci pro nalezení tlačítka:

def find_button_by_name(window, button_name):
    return window.findChild(QtGui.QPushButton, button_name)

Kterou použijeme takto:

    mainWindow = load_ui_form("form.ui")
    print(mainWindow)
 
    # získání reference na první tlačítko
    btn = find_button_by_name(mainWindow, "helloButton")

12. Demonstrační příklad – navázání akcí (funkcí) na tlačítka ve formuláři

V této chvíli již máme k dispozici všechny informace proto, abychom na jednotlivá tlačítka navázali callback funkce. Po stisku prvního tlačítka se zobrazí jednoduchý dialog, druhé tlačítko slouží k okamžitému ukončení aplikace. Se sloty a signály jsme se již v tomto seriálu setkali, takže jen krátce:

app = QtGui.QApplication(sys.argv)
mainWindow = load_ui_form("form.ui")
 
# získání reference na první tlačítko
buttonHello = find_button_by_name(mainWindow, "helloButton")
# navázání handleru na signál
buttonHello.clicked.connect(on_button_press)
 
# získání reference na druhé tlačítko
buttonQuit = find_button_by_name(mainWindow, "quitButton")
# navázání handleru na signál
buttonQuit.clicked.connect(QtCore.QCoreApplication.instance().quit)
 
mainWindow.show()

Úplný zdrojový kód tohoto demonstračního příkladu vypadá následovně:

#!/usr/bin/env python
# vim: set fileencoding=utf-8
 
# import "jádra" frameworku Qt i modulu pro GUI
from PySide import QtCore
from PySide import QtGui
 
# třída pro načtení formuláře
from PySide import QtUiTools
 
import sys
 
 
def load_ui_form(filename):
    ui_loader = QtUiTools.QUiLoader()
    return ui_loader.load(filename)
    return form
 
 
def find_button_by_name(window, button_name):
    return window.findChild(QtGui.QPushButton, button_name)
 
 
def on_button_press():
    # vytvoření dialogu
    msgBox = QtGui.QMessageBox()
 
    # nastavení zprávy a ikony, která se má zobrazit vedle zprávy
    msgBox.setText(u'Hello world!')
    msgBox.setIcon(QtGui.QMessageBox.Information)
 
    # zobrazení dialogu
    msgBox.exec_()
 
 
def main():
    QtGui.QApplication.setStyle("plastique")
    app = QtGui.QApplication(sys.argv)
    mainWindow = load_ui_form("form.ui")
    print(mainWindow)
 
    # získání reference na první tlačítko
    buttonHello = find_button_by_name(mainWindow, "helloButton")
    print(buttonHello)
    # navázání handleru na signál
    buttonHello.clicked.connect(on_button_press)
 
    # získání reference na druhé tlačítko
    buttonQuit = find_button_by_name(mainWindow, "quitButton")
    print(buttonHello)
    # navázání handleru na signál
    buttonQuit.clicked.connect(QtCore.QCoreApplication.instance().quit)
 
    mainWindow.show()
    sys.exit(app.exec_())
 
 
if __name__ == "__main__":
    main()

13. Alternativní cesta – vygenerování Pythonovského modulu z deklarativního zápisu formuláře

Programátoři, kteří potřebují v PySide použít formuláře vytvořené (například) v Qt Creatoru mají kromě explicitního načítání formulářů k dispozici ještě alternativní řešení. Formulář je totiž možné převést z XML souboru do plnohodnotného skriptu naprogramovaného v Pythonu. Pro tento převod se používá nástroj nazvaný pyside-uic, který je na většině distribucí součástí balíčku pyside-tools. Toto řešení může být v některých případech výhodnější než použití deklarace formulářů uložená v XML souborech, ovšem musíme mít na paměti, že se jedná o jednostranný převod, tj. jednou vygenerovaný soubor není možné (alespoň ne jednoduše) převést zpět do XML podoby, tedy do UI souboru. To znamená, že v repositáři většinou stejně zůstane zachován i původní UI soubor, aby bylo možné formuláře v případě potřeby upravovat. V navazujících kapitolách si ukážeme základy použití nástroje pyside-uic.

14. Instalace balíčku pyside-tools s nástrojem pyside-uic

Nejprve si ukažme, jakým způsobem se instaluje balíček pyside-tools, který nástroj pyside-uic obsahuje. Většinou bývá tento balíček součástí Linuxové distribuce, takže můžeme použít přímo správce balíčků (yum, apt-get, …):

# apt-get install pyside-tools
 
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  pyside-tools
0 upgraded, 1 newly installed, 0 to remove and 4 not upgraded.
Need to get 146 kB of archives.
After this operation, 485 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ trusty/universe pyside-tools amd64 0.2.15-1 [146 kB]
Fetched 146 kB in 0s (345 kB/s)
Selecting previously unselected package pyside-tools.
(Reading database ... 136176 files and directories currently installed.)
Preparing to unpack .../pyside-tools_0.2.15-1_amd64.deb ...
Unpacking pyside-tools (0.2.15-1) ...
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Setting up pyside-tools (0.2.15-1) ...

Další možností je instalace přes pip, což již ovšem vyžaduje instalaci dalších závislých balíčků (cmake atd.).

Po (doufejme) úspěšné instalaci si můžeme zobrazit základní nápovědu k tomuto nástroji:

$ pyside-uic --help
 
Usage: pyside-uic [options] <ui-file>
 
Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -p, --preview         show a preview of the UI instead of generating code
  -o FILE, --output=FILE
                        write generated code to FILE instead of stdout
  -x, --execute         generate extra code to test and display the class
  -d, --debug           show debug output
  -i N, --indent=N      set indent width to N spaces, tab if N is 0 (default:
                        4)
 
  Code generation options:
    --from-imports      generate imports relative to '.'

15. Vytvoření modulu s formulářem z jeho deklarativního popisu

Nyní si již můžeme vyzkoušet, jak dopadne překlad (či transformace) nám již známého formuláře form.ui do Pythonovského modulu. Nástroj pyside-uic vypisuje svůj výsledek na standardní výstup, takže musíme provést přesměrování do nového souboru:

$ pyside-uic form.ui > form.py

Výsledkem by měl být přibližně tento Pythonovský modul (ve skutečnosti může být výsledek nepatrně odlišný podle verze pyside-uic):

# -*- coding: utf-8 -*-
 
# Form implementation generated from reading ui file 'form.ui'
#
# Created: Tue May 15 20:52:00 2018
#      by: pyside-uic 0.2.15 running on PySide 1.2.1
#
# WARNING! All changes made in this file will be lost!
 
from PySide import QtCore, QtGui
 
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(271, 89)
        self.horizontalLayout = QtGui.QHBoxLayout(Form)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout = QtGui.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.helloButton = QtGui.QPushButton(Form)
        self.helloButton.setDefault(True)
        self.helloButton.setObjectName("helloButton")
        self.verticalLayout.addWidget(self.helloButton)
        self.quitButton = QtGui.QPushButton(Form)
        self.quitButton.setObjectName("quitButton")
        self.verticalLayout.addWidget(self.quitButton)
        self.horizontalLayout.addLayout(self.verticalLayout)
 
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
 
    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
        self.helloButton.setText(QtGui.QApplication.translate("Form", "Hello!", None, QtGui.QApplication.UnicodeUTF8))
        self.quitButton.setText(QtGui.QApplication.translate("Form", "Quit", None, QtGui.QApplication.UnicodeUTF8))

Z následujícího obrázku je patrné, že transformace byla provedena poměrně rigidně prvek po prvku:

Obrázek 16: UI soubor versus vygenerovaný skript napsaný v Pythonu.

16. Přidání kódu pro zobrazení formuláře

V případě, že při volání nástroje pyside-uic použijeme volbu -x, dojde k vygenerování Pythonovského modulu současně s kódem pro spuštění aplikace. To se hodí například při rychlém testování návrhu GUI atd. Pojďme si to vyzkoušet:

$ pyside-uic -x form.ui > form.py

Výsledek může vypadat například následovně. Můžeme vidět, že se skutečně jedná o spustitelný skript:

# -*- coding: utf-8 -*-
 
# Form implementation generated from reading ui file 'form.ui'
#
# Created: Tue May 15 20:57:21 2018
#      by: pyside-uic 0.2.15 running on PySide 1.2.1
#
# WARNING! All changes made in this file will be lost!
 
from PySide import QtCore, QtGui
 
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(271, 89)
        self.horizontalLayout = QtGui.QHBoxLayout(Form)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout = QtGui.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.helloButton = QtGui.QPushButton(Form)
        self.helloButton.setDefault(True)
        self.helloButton.setObjectName("helloButton")
        self.verticalLayout.addWidget(self.helloButton)
        self.quitButton = QtGui.QPushButton(Form)
        self.quitButton.setObjectName("quitButton")
        self.verticalLayout.addWidget(self.quitButton)
        self.horizontalLayout.addLayout(self.verticalLayout)
 
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
 
    def retranslateUi(self, Form):
        Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
        self.helloButton.setText(QtGui.QApplication.translate("Form", "Hello!", None, QtGui.QApplication.UnicodeUTF8))
        self.quitButton.setText(QtGui.QApplication.translate("Form", "Quit", None, QtGui.QApplication.UnicodeUTF8))
 
 
if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    Form = QtGui.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

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

Zdrojové kódy všech dnes popsaných demonstračních příkladů byly společně s deklaracemi formulářů (.ui), podobně jako tomu bylo i v předchozích článcích, uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/pre­sentations. Pokud nechcete klonovat celý repositář, můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

Deklarace formulářů použitých v demonstračních příkladech:

Zdrojové soubory vygenerované z formuláře:

18. Odkazy na Internetu

  1. Hand Coded GUI Versus Qt Designer GUI
    https://stackoverflow.com/qu­estions/387092/hand-coded-gui-versus-qt-designer-gui
  2. Qt Creator Manual
    http://doc.qt.io/qtcreator/
  3. Qt Designer Manual
    http://doc.qt.io/qt-5/qtdesigner-manual.html
  4. Qt Creator (Wikipedia)
    https://en.wikipedia.org/wi­ki/Qt_Creator
  5. QIODevice
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/QI­ODevice.html#PySide.QtCore­.QIODevice
  6. QFile
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/QFi­le.html#PySide.QtCore.QFi­le
  7. QUiLoader
    https://pyside.github.io/doc­s/pyside/PySide/QtUiTools/QU­iLoader.html#PySide.QtUiTo­ols.PySide.QtUiTools.QUiLo­ader.load
  8. QSvgWidget
    https://pyside.github.io/doc­s/pyside/PySide/QtSvg/QSvgWid­get.html
  9. QByteArray
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/QBy­teArray.html
  10. Python Bytes, Bytearray
    https://www.w3resource.com/pyt­hon/python-bytes.php
  11. psep-0101.txt (mj. popis mapování typů Pythonu na třídy v PySide)
    https://github.com/techto­nik/pseps/blob/master/psep-0101.txt
  12. QSvgRenderer
    https://pyside.github.io/doc­s/pyside/PySide/QtSvg/QSvgRen­derer.html
  13. QSvgGenerator
    https://pyside.github.io/doc­s/pyside/PySide/QtSvg/QSvgGe­nerator.html
  14. QIcon
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QIcon­.html
  15. PySide 1.2.1 documentation
    https://pyside.github.io/doc­s/pyside/index.html
  16. QStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QSty­le.html
  17. QCommonStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QCom­monStyle.html
  18. QPlastiqueStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QPlas­tiqueStyle.html
  19. QMacStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QMac­Style.html
  20. QCleanlooksStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QCle­anlooksStyle.html
  21. QGtkStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QGtkSty­le.html
  22. QCDEStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QCDES­tyle.html
  23. QMotifStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QMo­tifStyle.html
  24. QWindowsStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QWin­dowsStyle.html
  25. QStyleFactory
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QSty­leFactory.html
  26. QStyleOptionHeader
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QSty­leOptionHeader.html
  27. QAbstractSlider
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/Abstrac­tSlider.html
  28. QScrollBar
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/Scro­llBar.html
  29. QSlider
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/Sli­der.html
  30. QDial
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/Dial­.html
  31. QImage
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QIma­ge.html
  32. QPixmap
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QPix­map.html
  33. QBitmap
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QBit­map.html
  34. QPaintDevice
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QPa­intDevice.html
  35. QPicture
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QPic­ture.html
  36. QPainter
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QPa­inter.html
  37. QPainterPath
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QPa­interPath.html
  38. QGradient
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QGra­dient.html
  39. QLinearGradient
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QLi­nearGradient.html
  40. QRadialGradient
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QRa­dialGradient.html
  41. QTableWidget
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QTa­bleWidget.html
  42. QTableWidgetItem
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QTa­bleWidgetItem.html
  43. QTreeWidget
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QTre­eWidget.html
  44. QTreeWidgetItem
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QTre­eWidgetItem.html
  45. Afinní zobrazení
    https://cs.wikipedia.org/wi­ki/Afinn%C3%AD_zobrazen%C3%AD
  46. Differences Between PySide and PyQt
    https://wiki.qt.io/Differen­ces_Between_PySide_and_PyQt
  47. PySide 1.2.1 tutorials
    https://pyside.github.io/doc­s/pyside/tutorials/index.html
  48. PySide tutorial
    http://zetcode.com/gui/py­sidetutorial/
  49. Drawing in PySide
    http://zetcode.com/gui/py­sidetutorial/drawing/
  50. Qt Core
    https://pyside.github.io/doc­s/pyside/PySide/QtCore/Qt­.html
  51. QLayout
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QLa­yout.html
  52. QValidator
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QVa­lidator.html
  53. QStackedLayout
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QStac­kedLayout.html
  54. QFormLayout
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QFor­mLayout.html
  55. QBoxLayout
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QBox­Layout.html
  56. QHBoxLayout
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QHBox­Layout.html
  57. QVBoxLayout
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QVBox­Layout.html
  58. QGridLayout
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QGrid­Layout.html
  59. QAction
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QAc­tion.html
  60. QDialog
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QDi­alog.html
  61. QMessageBox
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QMes­sageBox.html
  62. QErrorMessage
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QError­Message.html
  63. QInputDialog
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QIn­putDialog.html
  64. QColorDialog
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QCo­lorDialog.html
  65. QListWidget
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QLis­tWidget.html
  66. Signals & Slots
    http://doc.qt.io/qt-4.8/signalsandslots.html
  67. Signals and Slots in PySide
    http://wiki.qt.io/Signals_an­d_Slots_in_PySide
  68. Intro to PySide/PyQt: Basic Widgets and Hello, World!
    http://www.pythoncentral.io/intro-to-pysidepyqt-basic-widgets-and-hello-world/
  69. QLineEdit
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QLi­neEdit.html
  70. QTextEdit
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QTex­tEdit.html
  71. QValidator
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QVa­lidator.html
  72. QIntValidator
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QIn­tValidator.html
  73. QRegExpValidator
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QRe­gExpValidator.html
  74. QWidget
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QWid­get.html
  75. QMainWindow
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QMa­inWindow.html
  76. QLabel
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QLa­bel.html
  77. QAbstractButton
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QAb­stractButton.html
  78. QCheckBox
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QChec­kBox.html
  79. QRadioButton
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QRa­dioButton.html
  80. QButtonGroup
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QBut­tonGroup.html
  81. QFrame
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QFra­me.html#PySide.QtGui.PySi­de.QtGui.QFrame
  82. QFrame.frameStyle
    https://pyside.github.io/doc­s/pyside/PySide/QtGui/QFra­me.html#PySide.QtGui.PySi­de.QtGui.QFrame.frameStyle
  83. Leo editor
    http://leoeditor.com/
  84. IPython Qt Console aneb vylepšený pseudoterminál
    https://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-ipython-a-ipython-notebook/#k06
  85. Vývojová prostředí ve Fedoře (4. díl)
    https://mojefedora.cz/vyvojova-prostredi-ve-fedore-4-dil/
  86. Seriál Letní škola programovacího jazyka Logo
    http://www.root.cz/serialy/letni-skola-programovaciho-jazyka-logo/
  87. Educational programming language
    http://en.wikipedia.org/wi­ki/Educational_programmin­g_language
  88. Logo Tree Project:
    http://www.elica.net/downlo­ad/papers/LogoTreeProject­.pdf
  89. Hra Breakout napísaná v Tkinteri
    https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/
  90. Hra Snake naprogramovaná v Pythone s pomocou Tkinter
    https://www.root.cz/clanky/hra-snake-naprogramovana-v-pythone-s-pomocou-tkinter/
  91. 24.1. turtle — Turtle graphics
    https://docs.python.org/3­.5/library/turtle.html#mo­dule-turtle
  92. TkDND
    http://freecode.com/projects/tkdnd
  93. Python Tkinter Fonts
    https://www.tutorialspoin­t.com/python/tk_fonts.htm
  94. The Tkinter Canvas Widget
    http://effbot.org/tkinter­book/canvas.htm
  95. Ovládací prvek (Wikipedia)
    https://cs.wikipedia.org/wi­ki/Ovl%C3%A1dac%C3%AD_prvek_­%28po%C4%8D%C3%ADta%C4%8D%29
  96. Rezervovaná klíčová slova v Pythonu
    https://docs.python.org/3/re­ference/lexical_analysis.html#ke­ywords
  97. TkDocs: Styles and Themes
    http://www.tkdocs.com/tuto­rial/styles.html
  98. Drawing in Tkinter
    http://zetcode.com/gui/tkin­ter/drawing/
  99. Changing ttk widget text color (StackOverflow)
    https://stackoverflow.com/qu­estions/16240477/changing-ttk-widget-text-color
  100. The Hitchhiker's Guide to Python: GUI Applications
    http://docs.python-guide.org/en/latest/scenarios/gui/
  101. 7 Top Python GUI Frameworks for 2017
    http://insights.dice.com/2014/11/26/5-top-python-guis-for-2015/
  102. GUI Programming in Python
    https://wiki.python.org/mo­in/GuiProgramming
  103. Cameron Laird's personal notes on Python GUIs
    http://phaseit.net/claird/com­p.lang.python/python_GUI.html
  104. Python GUI development
    http://pythoncentral.io/introduction-python-gui-development/
  105. Graphic User Interface FAQ
    https://docs.python.org/2/faq/gu­i.html#graphic-user-interface-faq
  106. TkInter
    https://wiki.python.org/moin/TkInter
  107. Tkinter 8.5 reference: a GUI for Python
    http://infohost.nmt.edu/tcc/hel­p/pubs/tkinter/web/index.html
  108. TkInter (Wikipedia)
    https://en.wikipedia.org/wiki/Tkinter
  109. appJar
    http://appjar.info/
  110. appJar (Wikipedia)
    https://en.wikipedia.org/wiki/AppJar
  111. appJar na Pythonhosted
    http://pythonhosted.org/appJar/
  112. appJar widgets
    http://appjar.info/pythonWidgets/
  113. Stránky projektu PyGTK
    http://www.pygtk.org/
  114. PyGTK (Wikipedia)
    https://cs.wikipedia.org/wiki/PyGTK
  115. Stránky projektu PyGObject
    https://wiki.gnome.org/Pro­jects/PyGObject
  116. Stránky projektu Kivy
    https://kivy.org/#home
  117. Stránky projektu PyQt
    https://riverbankcomputin­g.com/software/pyqt/intro
  118. PyQt (Wikipedia)
    https://cs.wikipedia.org/wiki/PyGTK
  119. Stránky projektu PySide
    https://wiki.qt.io/PySide
  120. PySide (Wikipedia)
    https://en.wikipedia.org/wiki/PySide
  121. Stránky projektu Kivy
    https://kivy.org/#home
  122. Kivy (framework, Wikipedia)
    https://en.wikipedia.org/wi­ki/Kivy_(framework)
  123. QML Applications
    http://doc.qt.io/qt-5/qmlapplications.html
  124. KDE
    https://www.kde.org/
  125. Qt
    https://www.qt.io/
  126. GNOME
    https://en.wikipedia.org/wiki/GNOME
  127. Category:Software that uses PyGTK
    https://en.wikipedia.org/wi­ki/Category:Software_that_u­ses_PyGTK
  128. Category:Software that uses PyGObject
    https://en.wikipedia.org/wi­ki/Category:Software_that_u­ses_PyGObject
  129. Category:Software that uses wxWidgets
    https://en.wikipedia.org/wi­ki/Category:Software_that_u­ses_wxWidgets
  130. GIO
    https://developer.gnome.or­g/gio/stable/
  131. GStreamer
    https://gstreamer.freedesktop.org/
  132. GStreamer (Wikipedia)
    https://en.wikipedia.org/wi­ki/GStreamer
  133. Wax Gui Toolkit
    https://wiki.python.org/moin/Wax
  134. Python Imaging Library (PIL)
    http://infohost.nmt.edu/tcc/hel­p/pubs/pil/
  135. 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/
  136. PySide na PyPi
    https://pypi.org/project/PySide/
Našli jste v článku chybu?