Hlavní navigace

Interaktivní tvorba grafického uživatelského rozhraní s využitím nástroje Pygubu (dokončení)

8. 4. 2021
Doba čtení: 41 minut

Sdílet

 Autor: Alejandro Autalan, Pygubu
Třetí článek o nástroji Pygubu určeného pro návrh grafického rozhraní. Ukážeme si automatické nastavování proměnných knihovnou Tkinter při běhu aplikace a nezapomeneme ani na popis základních vlastností kreslicího plátna.

Obsah

1. Pygubu designer ve funkci jednosměrného RAD

2. Vygenerování ukázkového zdrojového kódu

3. Vygenerování kódu založeného na knihovně Tkinter

4. Práce s dialogem obsahujícím zaškrtávací pole

5. Kostra demonstračního příkladu pro zobrazení dialogu se zaškrtávacími poli

6. Automatické nastavení proměnných při změně stavu zaškrtávacího pole

7. Zobrazení aktuálního stavu zaškrtávacích polí

8. Nastavení výchozího stavu zaškrtávacích polí

9. Widget představující vstupní textové pole

10. Realizace formuláře s textovým polem

11. Průběžná validace textu zapisovaného do textového pole

12. Realizace formuláře s validovaným textovým polem

13. Práce s grafikou v knihovně Tkinter

14. Widget canvas

15. Realizace formuláře s kreslicím plátnem (canvasem)

16. První skript, který zobrazí formulář s prázdným kreslicím plátnem

17. Kreslení na plátno

18. Ukázka dalších možností kreslicího plátna

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

20. Odkazy na Internetu

1. Pygubu designer ve funkci jednosměrného RAD

V předchozích dvou článcích jsme si na několika místech řekli, že Pygubu designer nelze považovat za plnohodnotný nástroj typu RAD (Rapid Application Development), a to především z toho důvodu, že se jedná o „pouhého“ návrháře GUI bez obousměrné vazby na zdrojový kód. Nicméně v poslední verzi Pygubu-designeru se objevila první vlaštovka RAD nástroje – Pygubu designer totiž nyní umožňuje z návrhu grafického uživatelského rozhraní vygenerovat dva typy zdrojových kódů, které budou ukázány v navazující dvojici kapitol.

Vraťme se nyní k poslední aplikaci, která byla popsána minule. Uživatelská část této aplikace se skládá z okna, do kterého je vložena pětice tlačítek:

Obrázek 1: Grafický návrh uživatelského rozhraní aplikace.

Tlačítka budou reagovat na operace provedené uživatelem, protože je u každého specifikována callback funkce (resp. přesněji řečeno metoda), která se zavolá po stisku tohoto tlačítka (libovolným ovladačem – klávesnicí nebo myší):

Obrázek 2: Nastavení callback funkce (resp. metody) i dalších parametrů jednotlivých tlačítek.

Při návrhu tohoto formuláře byl použit grid layout neboli mřížka, do které se jednotlivé ovládací prvky vkládají. U každého prvku lze určit, ke kterým okrajům buňky bude „přilepen“:

Obrázek 3: Použití grid layoutu (mřížky) a určení, ke kterým okrajům mřížky se mají tlačítka přilepit (sticky).

Vygenerovaný soubor s návrhem grafického uživatelského rozhraní by měl vypadat následovně:

<?xml version='1.0' encoding='utf-8'?>
<interface version="1.1">
  <object class="ttk.Frame" id="MainWindow">
    <property name="height">200</property>
    <property name="width">200</property>
    <layout manager="pack">
      <property name="propagate">True</property>
      <property name="side">top</property>
    </layout>
    <child>
      <object class="ttk.Button" id="ok_cancel">
        <property cbtype="simple" name="command" type="command">on_button_ok_cancel_click</property>
        <property name="text" translatable="yes">Ok + Cancel</property>
        <layout manager="grid">
          <property name="column">0</property>
          <property name="propagate">True</property>
          <property name="row">0</property>
          <property name="sticky">ew</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="retry_cancel">
        <property cbtype="simple" name="command" type="command">on_button_retry_cancel_click</property>
        <property name="text" translatable="yes">Retry + Cancel</property>
        <layout manager="grid">
          <property name="column">1</property>
          <property name="propagate">True</property>
          <property name="row">0</property>
          <property name="sticky">ew</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="yes_no">
        <property cbtype="simple" name="command" type="command">on_button_yes_no_click</property>
        <property name="text" translatable="yes">Yes + No</property>
        <layout manager="grid">
          <property name="column">0</property>
          <property name="propagate">True</property>
          <property name="row">1</property>
          <property name="sticky">ew</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="exit">
        <property cbtype="simple" name="command" type="command">on_button_exit_click</property>
        <property name="style">Red.TButton</property>
        <property name="text" translatable="yes">Exit</property>
        <layout manager="grid">
          <property name="column">1</property>
          <property name="propagate">True</property>
          <property name="row">4</property>
          <property name="sticky">ew</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="question">
        <property cbtype="simple" name="command" type="command">on_button_question_click</property>
        <property name="text" translatable="yes">Question</property>
        <layout manager="grid">
          <property name="column">1</property>
          <property name="propagate">True</property>
          <property name="row">1</property>
          <property name="sticky">ew</property>
        </layout>
      </object>
    </child>
  </object>
</interface>

2. Vygenerování ukázkového zdrojového kódu

V horní části uživatelského rozhraní nástroje Pygubu je možné se přepnout mezi taby Design a Code (což je právě ona novinka, která v dřívějších verzích nebyla dostupná). V případě, že se přepnete na tab Code, lze si tlačítkem Application nechat vygenerovat kostru aplikace (ovšem bez implementace callback metod atd.):

Obrázek 4: Vygenerování základní struktury kódu aplikace.

Vygenerovaný kód, který je závislý na knihovně pygubu, vypadá následovně:

import os
import pygubu
 
 
PROJECT_PATH = os.path.dirname(__file__)
PROJECT_UI = os.path.join(PROJECT_PATH, "example7.ui")
 
 
class Example7App:
    def __init__(self):
        self.builder = builder = pygubu.Builder()
        builder.add_resource_path(PROJECT_PATH)
        builder.add_from_file(PROJECT_UI)
        self.mainwindow = builder.get_object('MainWindow')
        builder.connect_callbacks(self)
 
    def on_button_ok_cancel_click(self):
        pass
 
    def on_button_retry_cancel_click(self):
        pass
 
    def on_button_yes_no_click(self):
        pass
 
    def on_button_exit_click(self):
        pass
 
    def on_button_question_click(self):
        pass
 
    def run(self):
        self.mainwindow.mainloop()
 
if __name__ == '__main__':
    import tkinter as tk
    root = tk.Tk()
    app = Example7App(root)
    app.run()

Jen pro zajímavost se podívejme na to, jak vypadala aplikace, kterou jsem vytvořil ručně v rámci předchozího článku:

"""Pygubu and Tkinter: changing style."""
 
# Example7.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example7App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('example7.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step #4: Configure callbacks
        builder.connect_callbacks(self)
 
        root.bind('<Control-q>', lambda event: self.on_button_exit_click())
 
    def on_button_ok_cancel_click(self):
        messagebox.askokcancel("askokcancel()", "askokcancel()")
 
    def on_button_yes_no_click(self):
        messagebox.askyesno("askyesno()", "askyesno()")
 
    def on_button_retry_cancel_click(self):
        messagebox.askretrycancel("askretrycancel()", "askretrycancel()")
 
    def on_button_question_click(self):
        messagebox.askquestion("askquestion()", "askquestion()")
 
    def on_button_exit_click(self):
        root.destroy()
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example7App(root)
    app.run()
Poznámka: podobnost obou zdrojových kódů spočívá v tom, že Pygubu nám nabízí vývojářům jednu cestu, kterou je možné se bez problémů ubírat (i když nám na druhou stranu další možnosti aktivně neblokuje).

3. Vygenerování kódu založeného na knihovně Tkinter

Druhé tlačítko, které na tabu Code nalezneme, se jmenuje Code Script. Toto tlačítko taktéž vygeneruje zdrojový kód, ovšem tento zdrojový kód již na knihovně pygubu nezávisí – jedinou závislostí je knihovna Tkinter, která je v Pythonu standardní. To vlastně znamená, že následující (vygenerovaný) kód by měl být spustitelný na každém počítači se standardně nainstalovaným Pythonem:

import tkinter as tk
import tkinter.ttk as ttk
 
 
class Example7App:
    def __init__(self, master=None):
        # build ui
        self.MainWindow = ttk.Frame(master)
        self.ok_cancel = ttk.Button(self.MainWindow)
        self.ok_cancel.configure(text='Ok + Cancel')
        self.ok_cancel.grid(column='0', row='0', sticky='ew')
        self.ok_cancel.configure(command=self.on_button_ok_cancel_click)
        self.retry_cancel = ttk.Button(self.MainWindow)
        self.retry_cancel.configure(text='Retry + Cancel')
        self.retry_cancel.grid(column='1', row='0', sticky='ew')
        self.retry_cancel.configure(command=self.on_button_retry_cancel_click)
        self.yes_no = ttk.Button(self.MainWindow)
        self.yes_no.configure(text='Yes + No')
        self.yes_no.grid(column='0', row='1', sticky='ew')
        self.yes_no.configure(command=self.on_button_yes_no_click)
        self.exit = ttk.Button(self.MainWindow)
        self.exit.configure(style='Red.TButton', text='Exit')
        self.exit.grid(column='1', row='4', sticky='ew')
        self.exit.configure(command=self.on_button_exit_click)
        self.question = ttk.Button(self.MainWindow)
        self.question.configure(text='Question')
        self.question.grid(column='1', row='1', sticky='ew')
        self.question.configure(command=self.on_button_question_click)
        self.MainWindow.configure(height='200', width='200')
        self.MainWindow.pack(side='top')
 
        # Main widget
        self.mainwindow = self.MainWindow
 
    def on_button_ok_cancel_click(self):
        pass
 
    def on_button_retry_cancel_click(self):
        pass
 
    def on_button_yes_no_click(self):
        pass
 
    def on_button_exit_click(self):
        pass
 
    def on_button_question_click(self):
        pass
 
    def run(self):
        self.mainwindow.mainloop()
 
if __name__ == '__main__':
    import tkinter as tk
    root = tk.Tk()
    app = Example7App(root)
    app.run()
Poznámka: po doplnění kódů callback metod se bude jednat o plně přenositelný skript.

4. Práce s dialogem obsahujícím zaškrtávací pole

Nyní již umíme reagovat na výběr těch ovládacích prvků, které přímo spouští nějakou akci. Typicky se jedná o položky menu a taktéž o příkazová tlačítka. Ovšem mnohdy se setkáme s nutností použít i zaškrtávací pole neboli checkboxy. I tyto prvky (widgety) pochopitelně v knihovně Tkinter existují a jsou přímo podporovány i Pygubu designerem. Vytvoříme si tedy návrh aplikace se třemi zaškrtávacími poli a taktéž s tlačítkem, které bude použito pro zobrazení stavu všech polí:

Obrázek 5: Návrh grafického uživatelského rozhraní aplikace se třemi zaškrtávacími poli.

Obrázek 6: Tlačítko Display Selections spustí callback metodu on_button_display_selections_click.

Obrázek 7: Pro změnu oproti předchozímu demonstračními příkladu nyní použijeme pack layout manager, kde u tlačítek zvolíme, že v horizontálním směru mají vyplnit celou šířku okna (parametr fill).

Výsledný soubor s popisem návrhu grafického uživatelského rozhraní aplikace by měl vypadat následovně:

<?xml version='1.0' encoding='utf-8'?>
<interface version="1.1">
  <object class="ttk.Frame" id="MainWindow">
    <property name="height">200</property>
    <property name="width">200</property>
    <layout manager="pack">
      <property name="propagate">True</property>
      <property name="side">top</property>
    </layout>
    <child>
      <object class="ttk.Checkbutton" id="checkbutton_a">
        <property name="text" translatable="yes">Selection A</property>
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Checkbutton" id="checkbutton_b">
        <property name="text" translatable="yes">Selection B</property>
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Checkbutton" id="checkbutton_c">
        <property name="text" translatable="yes">Selection C</property>
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_display_values">
        <property cbtype="simple" name="command" type="command">on_button_display_selections_click</property>
        <property name="compound">left</property>
        <property name="image">display.png</property>
        <property name="text" translatable="yes">Display selections</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_quit">
        <property cbtype="simple" name="command" type="command">on_quit_button_click</property>
        <property name="compound">left</property>
        <property name="image">application-exit.png</property>
        <property name="text" translatable="yes">Quit</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
  </object>
</interface>

5. Kostra demonstračního příkladu pro zobrazení dialogu se zaškrtávacími poli

Nejprve si ukažme kostru demonstračního příkladu, který po svém spuštění zobrazí dialog se zaškrtávacími poli. Prozatím jsou implementovány pouze dvě operace – reakce na stisk tlačítka pro ukončení aplikace a reakce na stisk klávesové zkratky Ctrl+Q se stejným významem – okamžité ukončení aplikace:

"""Pygubu and Tkinter: using check boxes."""
 
# Example8.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example8App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('example8.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step $4: Configure callbacks
        builder.connect_callbacks(self)
 
        root.bind('<Control-q>', lambda event: self.on_quit_button_click())
 
    def on_quit_button_click(self):
        root.destroy()
 
    def on_button_display_selections_click(self):
        pass
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example8App(root)
    app.run()

Obrázek 8: Po spuštění příkladu je zřejmé, že zaškrtávací pole mají tři stavy.

6. Automatické nastavení proměnných při změně stavu zaškrtávacího pole

Velmi praktická je další vlastnost widgetu checkbutton. Stav přepínacího tlačítka je totiž možné navázat na vybranou proměnnou, která tak bude automaticky sledovat jeho stav. Pokud je tlačítko nastaveno (je v něm znak × nebo ✓), bude do proměnné implicitně vložena hodnota 1, pokud je naopak nenastaveno, nastaví se nulová hodnota. Sledující proměnnou je v případě přímého použití knihovny Tkinter nutné vytvořit konstruktorem tkinter.IntVar() a specifikovat ji pojmenovaným parametrem variable:

delete_internet = tkinter.IntVar()
 
checkbutton = ttk.Checkbutton(root, text="Delete Internet?",
                              variable=delete_internet)

K hodnotě sledující proměnné se můžeme dostat s využitím getteru, tedy metody get():

checkbutton = ttk.Checkbutton(root, text="Delete Internet?",
                              variable=delete_internet,
                              command=lambda: print(delete_internet.get()))

V Pygubu designeru se toto chování nastavuje s využitím vlastnosti variable. Navíc je možné zvolit hodnotu proměnné ve chvíli, kdy je tlačítko vybráno (zašrkrtnuto) a kdy nikoli:

Obrázek 9: Nastavení vlastností zaškrtávacího tlačítka.

Soubor s návrhem grafického uživatelského rozhraní se změní následujícím způsobem:

<?xml version='1.0' encoding='utf-8'?>
<interface version="1.1">
  <object class="ttk.Frame" id="MainWindow">
    <property name="height">200</property>
    <property name="width">200</property>
    <layout manager="pack">
      <property name="propagate">True</property>
      <property name="side">top</property>
    </layout>
    <child>
      <object class="ttk.Checkbutton" id="checkbutton_a">
        <property name="offvalue">no</property>
        <property name="onvalue">yes</property>
        <property name="state">normal</property>
        <property name="text" translatable="yes">Selection A</property>
        <property name="variable">string:checkbutton_a</property>
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Checkbutton" id="checkbutton_b">
        <property name="offvalue">no</property>
        <property name="onvalue">yes</property>
        <property name="state">normal</property>
        <property name="text" translatable="yes">Selection B</property>
        <property name="variable">string:checkbutton_b</property>
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Checkbutton" id="checkbutton_c">
        <property name="offvalue">no</property>
        <property name="onvalue">yes</property>
        <property name="state">normal</property>
        <property name="text" translatable="yes">Selection C</property>
        <property name="variable">string:checkbutton_c</property>
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_display_values">
        <property cbtype="simple" name="command" type="command">on_button_display_selections_click</property>
        <property name="compound">left</property>
        <property name="image">display.png</property>
        <property name="text" translatable="yes">Display selections</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_quit">
        <property cbtype="simple" name="command" type="command">on_quit_button_click</property>
        <property name="compound">left</property>
        <property name="image">application-exit.png</property>
        <property name="text" translatable="yes">Quit</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
  </object>
</interface>

7. Zobrazení aktuálního stavu zaškrtávacích polí

V následujícím demonstračním příkladu je ukázáno, jakým způsobem lze zjistit aktuální stav zaškrtávacích polí. Nejprve přistoupíme k atributu tkvariables objektu builder:

vars = self.builder.tkvariables

Následně se k proměnným knihovny Tkinter přistupuje následovně:

vars["checkbutton_a"].get()
vars["checkbutton_b"].get()
vars["checkbutton_c"].get()

Konkrétně tedy můžeme snadno připravit zprávu pro dialogový box:

message = \
    "Checkbutton A: {}\n" \
    "Checkbutton B: {}\n" \
    "Checkbutton C: {}\n".format(vars["checkbutton_a"].get(),
                                 vars["checkbutton_b"].get(),
                                 vars["checkbutton_c"].get())

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

"""Pygubu and Tkinter: using check boxes."""
 
# Example9A.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example9App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('example9.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step #4: Configure callbacks
        builder.connect_callbacks(self)
 
        root.bind('<Control-q>', lambda event: self.on_quit_button_click())
 
    def on_quit_button_click(self):
        root.destroy()
 
    def on_button_display_selections_click(self):
        vars = self.builder.tkvariables
 
        message = \
            "Checkbutton A: {}\n" \
            "Checkbutton B: {}\n" \
            "Checkbutton C: {}\n".format(vars["checkbutton_a"].get(),
                                         vars["checkbutton_b"].get(),
                                         vars["checkbutton_c"].get())
        messagebox.askokcancel("askokcancel()", message)
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example9App(root)
    app.run()

8. Nastavení výchozího stavu zaškrtávacích polí

Výchozí stav zaškrtávacích polí je opět možné nastavit přes proměnné, které knihovna Tkinter sleduje, popř. nastavuje. V našem konkrétním příkladu, v němž máme definovány tři sledovací proměnné checkbutton_a, checkbutton_b a checkbutton_c pro trojici zaškrtávacích polí, se jejich nastavení do zvoleného výchozího stavu provede následujícím způsobem:

vars = self.builder.tkvariables
 
vars["checkbutton_a"].set("no")
vars["checkbutton_b"].set("no")
vars["checkbutton_c"].set("no")

Demonstrační příklad lze upravit takto (viz zvýrazněné části):

"""Pygubu and Tkinter: using check boxes."""
 
# Example9B.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example9App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('example9.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step #4: Configure callbacks
        builder.connect_callbacks(self)
 
        # step #5: Set variables
        vars = self.builder.tkvariables
        vars["checkbutton_a"].set("no")
        vars["checkbutton_b"].set("no")
        vars["checkbutton_c"].set("no")
 
        root.bind('<Control-q>', lambda event: self.on_quit_button_click())
 
    def on_quit_button_click(self):
        root.destroy()
 
    def on_button_display_selections_click(self):
        vars = self.builder.tkvariables
 
        message = \
            "Checkbutton A: {}\n" \
            "Checkbutton B: {}\n" \
            "Checkbutton C: {}\n".format(vars["checkbutton_a"].get(),
                                         vars["checkbutton_b"].get(),
                                         vars["checkbutton_c"].get())
        messagebox.askokcancel("Selections", message)
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example9App(root)
    app.run()

9. Widget představující vstupní textové pole

S využitím widgetu typu entry je možné v okně či dialogu zobrazit jeden řádek textu. Od staticky pojatého widgetu label se tento widget liší především v tom, že zobrazený řádek textu je možné editovat. Při editaci jsou k dispozici základní klávesy pro pohyb kurzoru (šipka doleva, šipka doprava, klávesa [Home] a klávesa [End]) a mimo jiné také další klávesové zkratky, které jsou známé například z shellu či editoru Emacs, Joe a Pico: [Ctrl+A] (posun na začátek textu), [Ctrl+E] (posun na konec textu). K tomu připočítejme dnes již standardní klávesy pro práci se schránkou: [Ctrl+C], [Ctrl+V] a [Ctrl+X] a na některých systémech i kombinace kláves [Ctrl+Insert], [Shift+Insert] a [Shift+Delete]. Bude ovšem fungovat i použití výběru, tedy stisk prostředního tlačítka myši vloží obsah výběru do widgetu entry.

Poznámka: pozor je nutné dát na to, že dochází k některým kolizím s dalšími ustálenými zkratkami. Týká se to především zkratky [Ctrl+A] pro přesun kurzoru na začátek textu v textovém poli versus rozšíření výběru na celé textové pole.

Text se do widgetu přiřazuje metodou insert:

entry = ttk.Entry(root)
entry.insert(0, "xyzzy")

I k widgetu entry je možné zaregistrovat „sledovací proměnnou“, jejíž hodnota bude reflektovat stav textu v tomto prvku. Sledovací proměnná bude mít typ StringVar:

value = tkinter.StringVar()

Nastavení sledování:

entry = ttk.Entry(root, textvariable=value)

Podobně lze postupovat i při použití Pygube designeru. Nejprve si ukažme, jak se textové pole vloží do formuláře a jak se definuje okraj okolo tohoto widgetu (textové pole je totiž jedním z widgetů, které typicky okolo sebe nějaký okraj vyžaduje kvůli vzhledu):

Obrázek 10: Návrh dialogu se vstupním textovým polem.

Obrázek 11: Úprava widgetu takovým způsobem, aby okolo něj vznikl nevyužitý okraj, který widget vizuálně odděluje od svého okolí.

Výsledný soubor s návrhem formuláře vypadá takto:

<?xml version='1.0' encoding='utf-8'?>
<interface version="1.1">
  <object class="ttk.Frame" id="MainWindow">
    <property name="height">200</property>
    <property name="width">200</property>
    <layout manager="pack">
      <property name="propagate">True</property>
      <property name="side">top</property>
    </layout>
    <child>
      <object class="ttk.Entry" id="text_entry">
        <property name="textvariable">string:input_text</property>
        <layout manager="pack">
          <property name="anchor">center</property>
          <property name="padx">10</property>
          <property name="pady">10</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_display_text">
        <property cbtype="simple" name="command" type="command">on_button_display_text_click</property>
        <property name="compound">left</property>
        <property name="image">display.png</property>
        <property name="text" translatable="yes">Display text</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_quit">
        <property cbtype="simple" name="command" type="command">on_quit_button_click</property>
        <property name="compound">left</property>
        <property name="image">application-exit.png</property>
        <property name="text" translatable="yes">Quit</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
  </object>
</interface>

10. Realizace formuláře s textovým polem

Podívejme se nyní na způsob realizace programové části formuláře, který obsahuje textové pole. Při inicializaci formuláře nastavíme sledovací proměnnou nazvanou input_text na zvolenou výchozí hodnotu, což se ihned projeví i ve vlastním formuláři zobrazeném uživateli:

vars = self.builder.tkvariables
vars["input_text"].set("")

Následně implementujeme tělo callback metody zavolané ve chvíli, kdy uživatel klikne na tlačítko určené pro zobrazení aktuálního obsahu textového pole. Vše je opět vyřešeno přes sledovací proměnnou:

def on_button_display_text_click(self):
    vars = self.builder.tkvariables
    text = vars["input_text"].get()

Úplný zdrojový kód v pořadí již desátého demonstračního příkladu vypadá následovně. Zvýrazněny jsou ty části kódu, které se týkají zpracování textu z textového pole:

"""Pygubu and Tkinter: text entry."""
 
# Example10.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example10App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('exampleA.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step #4: Configure callbacks
        builder.connect_callbacks(self)
 
        # step #5: Set variables
        vars = self.builder.tkvariables
        vars["input_text"].set("")
 
        root.bind('<Control-q>', lambda event: self.on_quit_button_click())
 
    def on_quit_button_click(self):
        root.destroy()
 
    def on_button_display_text_click(self):
        vars = self.builder.tkvariables
        text = vars["input_text"].get()
 
        messagebox.askokcancel("Text entered by user:", text)
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example10App(root)
    app.run()

11. Průběžná validace textu zapisovaného do textového pole

V mnoha aplikacích se setkáme s požadavkem na textové pole, jehož vstup je nějakým způsobem omezený (a následně validovaný). Příkladem může být textové pole určené pro zápis kladného čísla, pole pro vstup rodného čísla, čísla platební karty atd. atd. I tuto kontrolu je možné v knihovně Tkinter zajistit – a to buď průběžně (již v průběhu zadávání textu) nebo až následně, po ukončení zadávání (a oba způsoby mají své pro i proti). Ukážeme si způsob průběžné validace textu přímo při jeho zápisu, což vlastně znamená, že neplatné znaky nebude vůbec možné do textového pole vložit:

Obrázek 12: Nastavení validace zapisovaného textu. Pokud je zapotřebí zajistit kontrolu prováděnou ihned při zápisu jednotlivých znaků, je nutné ve vlastnosti validate zvolit volbu key.

Obrázek 13: Specifikace argumentu předávaného validátoru. Hodnota zadávaná do textového pole bude průběžně posílána do zvolené callback metody nazvaný validate_input_text. To zajišťuje parametr %P.

Výsledný návrh formuláře, který nyní obsahuje i specifikaci chování (což je důležité – chování GUI je součástí návrhu GUI a nikoli logiky aplikace), bude vypadat takto:

<?xml version='1.0' encoding='utf-8'?>
<interface version="1.1">
  <object class="ttk.Frame" id="MainWindow">
    <property name="height">200</property>
    <property name="width">200</property>
    <layout manager="pack">
      <property name="propagate">True</property>
      <property name="side">top</property>
    </layout>
    <child>
      <object class="ttk.Entry" id="text_entry">
        <property name="textvariable">string:input_text</property>
        <property name="validate">key</property>
        <property args="%P" cbtype="entry_validate" name="validatecommand" type="command">validate_input_text</property>
        <layout manager="pack">
          <property name="anchor">center</property>
          <property name="padx">10</property>
          <property name="pady">10</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_display_text">
        <property cbtype="simple" name="command" type="command">on_button_display_text_click</property>
        <property name="compound">left</property>
        <property name="image">display.png</property>
        <property name="text" translatable="yes">Display text</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="button_quit">
        <property cbtype="simple" name="command" type="command">on_quit_button_click</property>
        <property name="compound">left</property>
        <property name="image">application-exit.png</property>
        <property name="text" translatable="yes">Quit</property>
        <layout manager="pack">
          <property name="expand">true</property>
          <property name="fill">x</property>
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
  </object>
</interface>

12. Realizace formuláře s validovaným textovým polem

Metoda určená pro průběžnou validaci zadávaného textu bude kontrolovat, zda text obsahuje číslice, popř. jestli je textové pole prázdné (což je výchozí stav). Implementace validátoru je v tomto případě triviální, protože výsledek validace odpovídá návratové hodnotě validátoru:

def validate_input_text(self, value):
    if value.isdigit():
        return True
    elif value is "":
        return True
    else:
        return False
Poznámka: pochopitelně je možné přidat další validátor použitý PO zápisu textu, tj. ve chvíli, kdy textové pole ztratí fokus. V takovém případě bychom kontrolovali (či mohli kontrolovat) i to, zda není textové pole prázdné.

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

"""Pygubu and Tkinter: text entry and validators."""
 
# Example11.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example11App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('exampleB.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step #4: Configure callbacks
        builder.connect_callbacks(self)
 
        # step #5: Set variables
        vars = self.builder.tkvariables
        vars["input_text"].set("")
 
        root.bind('<Control-q>', lambda event: self.on_quit_button_click())
 
    def on_quit_button_click(self):
        root.destroy()
 
    def on_button_display_text_click(self):
        vars = self.builder.tkvariables
        text = vars["input_text"].get()
 
        messagebox.askokcancel("Text entered by user:", text)
 
    def validate_input_text(self, value):
        if value.isdigit():
            return True
        elif value is "":
            return True
        else:
            return False
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example11App(root)
    app.run()

13. Práce s grafikou v knihovně Tkinter

Práci s grafikou můžeme chápat ve dvou úrovních. Na vyšší úrovni manipulujeme s jednotlivými geometricky popsanými tvary, jakými jsou například úsečka, obdélník, kruh, text či spline křivka. Každému tvaru může být přiřazeno značné množství atributů, jedná se například o tloušťku čáry, kterou je vykreslena hranice objektu, barva a styl výplně uzavřených objektů či font vykreslovaného textu. Na úrovni nižší se může manipulovat přímo s pixely, které tvoří zobrazovaný rastrový obrázek. V knihovně Tkinter je pro práci na vyšší úrovni určen widget canvas spolu s dalšími objektu, na nižší úrovni pak widgety (resp. objekty) bitmap, image a photo. Objekt typu image přitom zapouzdřuje více typů obrázků, od monochromatického BitmapImage přes vícebarevný PhotoImage až po uživatelsky vytvářené formáty.

14. Widget canvas

Jak jsme si již řekli v předchozí kapitole, je pro práci s grafikou na vyšší úrovni nabízen v knihovně Tkinter widget canvas, česky bychom mohli tento název přeložit jako (malířské) plátno. Nenechte se ovšem zmýlit tímto názvem, který má v jiných programových knihovnách odlišný (většinou jednodušší) význam, zde se skutečně jedná o velmi mocný widget, který současně slouží jako kontejner pro další objekty.

Vkládané objekty si své vlastnosti zachovávají, tj. lze s nimi i po jejich vykreslení interaktivně i programově pohybovat, měnit jejich vlastnosti apod. K tomu musíme připočítat možnost uložit celé plátno do PostScriptového souboru se zachováním vektorových charakteristik plátna (tj. neprovádí se ztrátový převod na bitmapy). To mj. znamená, že se vlastnosti canvasu do určité míry podobají použití SVG na webových stránkách; naproti tomu „webový canvas“ je vlastně pouze bitmapa, do níž se objekty vykreslují a ihned po jejich vykreslení se jejich vlastnosti ztratí (zůstanou jen barevné pixely).

Každý objekt, který je na plátno umístěn, musí mít specifikovány souřadnice počátečního a koncového bodu, v případě lomených čar, spline křivek a polygonů se samozřejmě specifikuje bodů více. Souřadnice bodů mohou být zadány pomocí více jednotek, jež se rozlišují podle jednoho písmene zapsaného za numerickou hodnotou (hodnoty jsou samozřejmě platné pouze při správně nakalibrované obrazovce, což kupodivu mnoho systémů dodnes nedodržuje):

Přípona Význam
m milimetry
c centimetry
i palce
p body (implicitní hodnota)
Poznámka: v případě, že potřebujete použít například milimetry, je nutné souřadnice zapisovat do řetězce.

V následující tabulce je ukázáno, jaké objekty je možné na plátno pokládat (a tím je vlastně ihned vykreslit):

Jméno objektu Význam
arc kruhový nebo eliptický oblouk
bitmap bitmapový obrázek
image obecně vícebarevný rastrový obrázek
line úsečka, lomená úsečka nebo dokonce hladká spline křivka (!)
oval uzavřená kružnice nebo elipsa
polygon uzavřený polygon či tvar vytvořený ze spline křivek
rectangle čtverec nebo obdélník
text textový řetězec
window vnořené okno se samostatným řízením

15. Realizace formuláře s kreslicím plátnem (canvasem)

Pro otestování některých možností, které nám kreslicí plátno nabízí, vytvoříme jednoduchý formulář, který bude prozatím obsahovat pouze vlastní plátno a taktéž tlačítko sloužící pro ukončení činnosti aplikace:

Obrázek 14: Návrh dialogu s jediným tlačítkem a s kreslicí plochou.

Vlastní návrh formuláře je v tomto případě skutečně triviální:

<?xml version='1.0' encoding='utf-8'?>
<interface version="1.1">
  <object class="ttk.Frame" id="MainWindow">
    <property name="height">200</property>
    <property name="width">200</property>
    <layout manager="pack">
      <property name="propagate">True</property>
      <property name="side">top</property>
    </layout>
    <child>
      <object class="tk.Canvas" id="canvas">
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
    <child>
      <object class="ttk.Button" id="quit">
        <property cbtype="simple" name="command" type="command">on_quit_button_click</property>
        <property name="text" translatable="yes">Quit</property>
        <layout manager="pack">
          <property name="propagate">True</property>
          <property name="side">top</property>
        </layout>
      </object>
    </child>
  </object>
</interface>
Poznámka: povšimněte si, že jsme opět využili správce geometrie pack a nikoli grid, i když naprosto stejného výsledku lze dosáhnout s využitím obou správců.

16. První skript, který zobrazí formulář s prázdným kreslicím plátnem

Skript, který bez dalších operací pouze zobrazí formulář obsahující prázdné kreslicí plátno a bude očekávat uzavření formuláře (a tím pádem i ukončení celé aplikace), bude vypadat následovně:

"""Pygubu and Tkinter: changing style."""
 
# Example12.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example12App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('exampleC.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step #4: Configure callbacks
        builder.connect_callbacks(self)
 
        root.bind('<Control-q>', lambda event: self.on_quit_button_click())
 
    def on_quit_button_click(self):
        root.destroy()
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example12App(root)
    app.run()

17. Kreslení na plátno

V následujícím demonstračním příkladu je ukázáno jednoduché použití plátna, na které jsou s využitím metody create_TYP_OBJEKTU vloženy jednoduché objekty – úsečka, kruh, text, polygon atd.. Vzhledem k tomu, že se při specifikaci souřadnic neuvádí u číselných hodnot žádná přípona (používáme celá čísla), předpokládá se, že jsou všechny hodnoty zapsané v bodech (pixelech). To také znamená, že na různých obrazovkách a při různých rozlišeních budou mít nakreslené objekty jinou velikost, což nám v tomto případě nemusí vadit.

Obrázek 15: Nastavení minimální výšky kreslicího plátna.

Grafické objekty vkládané na plátno mohou mít nastaveno velké množství vlastností, jak je ukázáno na modifikaci předchozího příkladu (nejsou zde ukázány zdaleka všechny vlastnosti, ty jsou uvedeny a podrobně popsány v helpu):

Vlastnost Popis
outline barva obrysu
fill barva výplně
width šířka obrysu
dash vzorek při vykreslování úseček a polyčar
font popis použitého fontu

Některé z těchto vlastností v příkladu určujeme, například:

canvas.create_arc(100, 1, 200, 100, outline='blue', start=45,
                  extent=180, style=tk.ARC, width=2)
 
canvas.create_oval(325, 25, 375, 75, fill="#a0a0ff")
 
canvas.create_text(300, 150, text="Hello world!", font="Helvetica 20")

Obrázek 16: Vykreslení základních obrazců na plátno.

Úplný kód dnešního posledního demonstračního příkladu:

"""Pygubu and Tkinter: changing style."""
 
# Example13.py
 
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import pygubu
 
 
class Example13App(pygubu.TkApplication):
    """Class representing a Tkinter based application."""
 
    def _create_ui(self):
        """Construct and initializes all UI-related data structures."""
        # step #1: Create a builder
        self.builder = builder = pygubu.Builder()
 
        # step #2: Load an ui file
        builder.add_from_file('exampleD.ui')
 
        # step #2B: Specify path to images and other resources
        builder.add_resource_path(".")
 
        # step #3: Create the mainwindow
        self.mainwindow = builder.get_object('MainWindow', self.master)
 
        # step #4: Configure callbacks
        builder.connect_callbacks(self)
 
        root.bind('<Control-q>', lambda event: self.on_quit_button_click())
        root.bind('<Control-d>', lambda event: self.on_draw_button_click())
 
    def on_quit_button_click(self):
        root.destroy()
 
    def on_draw_button_click(self):
        canvas = self.builder.get_object("canvas")
 
        width = canvas.winfo_width()
        height = canvas.winfo_height()
        grid_size = 30
 
        # draw something onto canvas
        for x in range(0, width, grid_size):
            canvas.create_line(x, 0, x, height, dash=7, fill="gray")
        for y in range(0, height, grid_size):
            canvas.create_line(0, y, width, y, dash=7, fill="gray")
 
        canvas.create_line(0, 0, 100, 100, fill='red', width=2, dash=8)
 
        canvas.create_arc(100, 1, 200, 100, outline='blue', start=45,
                          extent=180, style=tk.ARC, width=2)
 
        canvas.create_oval(200, 1, 300, 100)
 
        canvas.create_oval(325, 25, 375, 75, fill="#a0a0ff")
 
        canvas.create_rectangle(50, 125, 150, 175, fill="#a0a0ff")
 
        canvas.create_text(300, 150, text="Hello world!", font="Helvetica 20")
 
        canvas.create_polygon(50, 205, 200, 280, 50, 355, fill="#80ff80")
 
        canvas.create_polygon(230, 205, 370, 280, 230, 355, fill="black",
                              outline="red", width="5")
 
 
if __name__ == '__main__':
    # needed to have a menu
    root = tk.Tk()
 
    # style
    style = ttk.Style()
 
    # run the application
    app = Example13App(root)
    app.run()

18. Ukázka dalších možností kreslicího plátna

S využitím plátna je relativně snadné a přímočaré implementovat i různé graficky orientované nástroje, například následující systém pro nalezení a vykreslení obrysů místností o kterých jsou informace uložené v SAPu (přesněji řečeno tento CAD systém komunikuje s webovou službou, která obsahuje kontektor do SAPu).

Obrázek 17: Specializovaný CAD systém vytvořený v kombinaci Python+Tkinter.

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

Zdrojové kódy všech předminule, minule i dnes popsaných demonstračních příkladů určených pro Python 3 a nejnovější stabilní verzi knihovny Pygubu (a pochopitelně i pro Pygubu designer) byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs. V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má velikost zhruba několik desítek kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

# Jméno souboru Stručný popis souboru Cesta
    Ovládací prvky vložené do hlavního okna aplikace  
1 example1.ui soubor s návrhem GUI prvního demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example1.ui
2 example1.py implementace prvního demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example1.py
       
    Menu, jehož jednotlivé položky obsahují i ikony  
3 example2.ui soubor s návrhem GUI druhého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example2.ui
4 example2A.py implementace třetího demonstračního příkladu (bez menu) https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example2A.py
5 example2B.py implementace třetího demonstračního příkladu (nespecifikován adresář s ikonami) https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example2B.py
6 example2C.py implementace třetího demonstračního příkladu (korektní varianta) https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example2C.py
       
    Menu, jehož položky volají zvolené metody  
7 example3.ui soubor s návrhem GUI třetího demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example3.ui
8 example3.py implementace třetího demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example3.py
       
    „Odtrhávací“ menu  
9 example4.ui soubor s návrhem GUI čtvrtého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example4.ui
10 example4.py implementace čtvrtého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example4.py
       
    Klávesové zkratky přiřazené položkám menu  
11 example5.ui soubor s návrhem GUI pátého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example5.ui
12 example5.py implementace pátého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example5.py
13 example5B.py implementace pátého demonstračního příkladu s reakcemi na stisk kláves https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example5B.py
       
    Změna tématu zobrazení za běhu aplikace  
14 example6.ui soubor s návrhem GUI šestého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example6.ui
15 example6.py implementace šestého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example6.py
       
    Standardní dialogová okna  
16 example7.ui soubor s návrhem GUI sedmého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example7.ui
17 example7.py implementace sedmého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example7.py
       
    Práce s dialogem obsahujícím zaškrtávací pole  
18 example8.ui soubor s návrhem GUI osmého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example8.ui
19 example8.py implementace osmého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example8.py
       
    Automatické nastavení proměnných při změně stavu zaškrtávacího pole  
20 example9.ui soubor s návrhem GUI devátého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example9.ui
21 example9.py implementace devátého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/example9.py
       
    Realizace formuláře s textovým polem  
22 exampleA.ui soubor s návrhem GUI desátého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleA.ui
23 exampleA.py implementace desátého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleA.py
       
    Realizace formuláře s validovaným textovým polem  
24 exampleB.ui soubor s návrhem GUI jedenáctého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleB.ui
25 exampleB.py implementace jedenáctého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleB.py
       
    Realizace formuláře s kreslicím plátnem (canvasem)  
26 exampleC.ui soubor s návrhem GUI dvanáctého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleC.ui
27 exampleC.py implementace dvanáctého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleC.py
       
    Kreslení do canvasu  
28 exampleD.ui soubor s návrhem GUI třináctého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleD.ui
29 exampleD.py implementace třináctého demonstračního příkladu https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/exampleD.py

Ve druhém a třetím demonstračním příkladu, jsou navíc použity i ikony v menu, stejně jako v příkladech používajících tlačítko pro uzavření aplikace. Tyto ikony jsou uloženy samostatně ve formátu PNG a měly by být umístěny do stejného adresáře, ze kterého se spouští aplikace:

# Jméno souboru Stručný popis souboru Cesta
1 application-exit.png ikona pro položku menu sloužící k ukončení aplikace https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/application-exit.png
2 document-new.png ikona pro položku menu File→New https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/document-new.png
3 document-open.png ikona pro položku menu File→Open https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/document-open.png
4 edit-copy.png ikona pro položku menu Edit→Copy https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/edit-copy.png
5 edit-cut.png ikona pro položku menu Edit→Cut https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/edit-cut.png
6 edit-paste.png ikona pro položku menu Edit→Paste https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/edit-paste.png
7 edit-delete.png ikona pro položku menu Edit→Delete https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/edit-delete.png
     
8 application-exit.png ikona pro tlačítko použité pro ukončení aplikace https://github.com/tisnik/most-popular-python-libs/blob/master/pygubu/application-exit.png

20. Odkazy na Internetu

  1. Seriál Grafické uživatelské rozhraní v Pythonu
    https://www.root.cz/serialy/graficke-uzivatelske-rozhrani-v-pythonu/
  2. Pygubu na PyPi
    https://pypi.org/project/pygubu/
  3. Repositář projektu Pygubu
    https://github.com/alejan­droautalan/pygubu
  4. pygubu-designer na PyPi
    https://pypi.org/project/pygubu-designer/
  5. Repositář projektu pygubu-designer
    https://github.com/alejan­droautalan/pygubu-designer
  6. Pygubu Wiki
    https://github.com/alejan­droautalan/pygubu/wiki
  7. How to install Tkinter in Python?
    https://www.tutorialspoint.com/how-to-install-tkinter-in-python
  8. Stránky projektu Glade
    https://glade.gnome.org/
  9. Hra Breakout napísaná v Tkinteri
    https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/
  10. Brython aneb použití jazyka Python ve skriptech přímo v prohlížeči
    https://www.root.cz/clanky/brython-aneb-pouziti-jazyka-python-ve-skriptech-primo-v-prohlizeci/
  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. Rapid application development
    https://en.wikipedia.org/wi­ki/Rapid_application_deve­lopment
  21. Non-functional requirement
    https://en.wikipedia.org/wiki/Non-functional_requirement
  22. Graphical user interface builder
    https://en.wikipedia.org/wi­ki/Graphical_user_interfa­ce_builder
  23. User interface markup language
    https://en.wikipedia.org/wi­ki/User_interface_markup_lan­guage
  24. Top 10 programming languages that developers hate the most
    https://www.techworm.net/2017/11/perl-hated-programming-language-developers-says-report.html
  25. Raspberry Pi Tutorial: Create your own GUI (Graphical User Interface) with TkInter and Python
    https://www.youtube.com/wat­ch?v=Bvq0LdBn0dY
  26. Raspberry Pi Workshop – Chapter 4 – Your First GUI with TkInter and Python
    https://www.youtube.com/watch?v=ap-ABFNCBoE

Autor článku

Pavel Tišnovský vystudoval VUT FIT a v současné době pracuje ve společnosti Red Hat, kde vyvíjí nástroje pro OpenShift.io.