Letní akce! Lákají tě IT školení C#, Javy a PHP v Brně? Přihlas se a napiš nám do zpráv kód "BRNO 500" pro slevu 500 Kč na libovolný brněnský kurz. Lze kombinovat se slevami uvedenými u školení i použít pro více kurzů. Akce končí 28.7.

Lekce 3 - Upomínač narozenin v PyQt - Návrh formulářů

Python Okenní aplikace Upomínač narozenin v PyQt - Návrh formulářů

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Aplikace Kalkulačka v PyQt, jsme se naučili obsluhovat události a vytvořili jednoduchou kalkulačku. V dnešním Python tutoriálu začneme v PyQt pracovat na aplikaci k upomínání narozenin přátel. Aplikace bude vypadat následovně:

Aplikace na upomínání narozenin v Python a PyQt

Struktura aplikace

Vytvořte si nový projekt, já soubor opět pojmenuji main.py. Jako vždy začneme formuláři. Tentokrát již budeme mít v aplikaci dva, PrehledForm s přehledem osob a jejich narozenin a OsobaForm k přidávání nových osob. Co se týká vytvoření samotné aplikace, přejdeme ještě dále a i tu dnes vytvoříme přes třídu App. Všechny tyto třídy si připravíme a do třídy App přidáme metodu build(), která nám naši aplikaci spustí. Třída App bude udržovat instance našich dalších tříd, nyní formulářů.

from PyQt5 import QtWidgets, QtGui, QtCore
import sys

class OsobaForm(QtWidgets.QWidget):

        def __init__(self, **kwargs):
                super(OsobaForm, self).__init__(**kwargs)
                pass

        def setup(self):
                pass

class PrehledForm(QtWidgets.QMainWindow):

        def __init__(self, **kwargs):
                super(PrehledForm, self).__init__(**kwargs)
                pass

        def setup(self):
                self.osoba_form = root.osoba_form

class App(QtWidgets.QApplication):

        def __init__(self):
                super(App, self).__init__(sys.argv)

        def build(self):
                self.prehled_form = PrehledForm()
                self.osoba_form = OsobaForm()

                self.prehled_form.setup()
                self.osoba_form.setup()
                sys.exit(self.exec_())

root = App()
root.build()

Oba formuláře jsou opět vytvořené jako třídy dědící z QtWidgets.QWidget. Kromě konstruktoru (metody __init__()) v nich máme i metodu setup(), kterou spustíme až po vytvoření všech formulářů. Tímto způsobem k sobě budou moci formuláře vzájemně přistupovat. Všimněte si, že v metodě build() třídy App() vytvoříme oba formuláře a až poté oběma zavoláme metodu setup(). Formulář PrehledForm si v ní uloží instanci OsobaForm, kterou si z aplikace vytáhne pomocí klíčového slova root. Formulář s přehledem bude takto moci formulář pro osobu otevírat při kliknutí na tlačítko "Přidat".

Kostru formulářů a aplikace máme vytvořenou, i když aplikace zatím po spuštění nic neudělá.

Návrh formulářů

Přesuňme se ke vkládání jednotlivých widgetů do formulářů.

Přehledový formulář

Přehledový formulář je základní okno aplikace s přehledem osob a jejich narozenin. Budeme potřebovat následující ovládací prvky:

  • 8x QLabel - Popisky
  • 2x QPushButton - Tlačítko na přidání a odebrání osoby
  • 1x QListWidget - Seznam osob
  • 1x QCalendarWidget - Kalendář

Layout

Jako první musíme samozřejmě vytvořit systém layoutů, aby se widgety ve formuláři správně poskládaly. Jelikož veškeré GUI zde píšeme jako kód a nepoužíváme žádný GUI designer, budeme postupovat jednoduše shora dolů a zleva doprava. Celému formuláři nastavíme QVBoxLayout, čímž se v něm další layouty budou řadit pod sebe. V tomto formuláři budeme box layouty využívat často.

Informační boxy

Layout labelů v PyQt formuláři

Na část vyznačenou červeně na obrázku budeme potřebovat:

  • QHBoxLayout - umožní řádit labely vedle sebe
    • QLabel - Popisek s textem "Dnes je"
    • QLabel - Popisek s dnešním datem
  • QHBoxLayout - umožní řádit labely vedle sebe
    • QLabel - Popisek s textem "Nejbližší narozeniny"
    • QLabel - Popisek s nejbližšími narozeninami (zatím nebude použitý)

Nejprve si na začátek souboru přidejte:

import datetime

Tím jsme si naimportovali funkcionalitu pro práci s datem a časem a budeme schopní do QLabelu zobrazit co je dnes za den. Ukažme si nyní upravený kód třídy PrehledForm, který si následně podrobně popíšeme.

class PrehledForm(QtWidgets.QMainWindow):

        def __init__(self, **kwargs):
                super(PrehledForm, self).__init__(**kwargs)

                # Titulek, ikonka a minimální šířka okna
                self.setWindowTitle("Výročí")
                self.setWindowIcon(QtGui.QIcon("icon.png"))
                self.setMinimumWidth(650)

                # Vytvoříme hlavní widget a nastavíme BoxLayout
                formular = QtWidgets.QWidget()
                layoutFormulare = QtWidgets.QVBoxLayout()
                formular.setLayout(layoutFormulare)
                self.setCentralWidget(formular)

                # Vytvoříme informační box s BoxLayoutem (Dnešní datum)
                self.dnesLayout = QtWidgets.QHBoxLayout()
                layoutFormulare.addLayout(self.dnesLayout)
                self.dnesLayout.addWidget(QtWidgets.QLabel("Dnes je:"))
                self.dnesLayout.addStretch()
                self.dnesLabel = QtWidgets.QLabel(self.get_current_date())
                self.dnesLayout.addWidget(self.dnesLabel)

                # Vytvoříme informační box s BoxLayoutem (Nejbližší narozeniny)
                self.narozeninyLayout = QtWidgets.QHBoxLayout()
                layoutFormulare.addLayout(self.narozeninyLayout)
                self.narozeninyLayout.addWidget(QtWidgets.QLabel("Nejbližší narozeniny:"))
                self.narozeninyLayout.addStretch()
                self.nejblizsiLabel = QtWidgets.QLabel("")
                self.narozeninyLayout.addWidget(self.nejblizsiLabel)

                self.show()

        def get_current_date(self):
                return (str(datetime.datetime.now().day) + "." + str(datetime.datetime.now().month)
                + "." + str(datetime.datetime.now().year))

        # Získá požadované instance
        def setup(self):
                self.osoba_form = root.osoba_form

První trojice řádků nastavuje titulek okna, jeho ikonku a minimální šířku, aby se okno nedalo zmenšit tak, že by se do něj obsah nevešel. Ikonku, která se vám líbí, si můžete najít na https://www.iconfinder.com/ nebo si stáhnout ikony přiložené v dnešním archivu. Soubor poté stačí umístit do složky se souborem main.py. Když ji nenastavíte nebo dokonce i když ji nastavíte a nenahrajete, vadit to nebude.

Další řádky vytvářejí samotný formulář a nastavují mu QVBoxLayout pro řazení widgetů (přesněji dalších layoutů) pod sebe. Formulář se následně nastaví aplikaci jako výchozí.

První informační boxík s dnešním datem vytváříme tedy jako QHBoxLayout. Na kódu je zajímavé asi jen to, že aby byly QLabely naproti sobě, je mezi ně vloženo prázdné místo pomocí addStretch().

Nakonec následuje vytvoření druhého boxíku s dnešními narozeninami, situace je zde úplně stejná jako v boxíku předchozím.

Metoda get_current_date() vrátí aktuální datum v českém formátu (mm.dd.rrrr) a měla by být z kódu srozumitelná.

Pokud spustíte aplikaci, zobrazí se vám následující okénko:

Přehledový formulář upomínače narozenin v Pythonu

ListWidget, kalendář a informace o osobě

Základní informace máme hotové a nyní vytvoříme layouty pro QListWidget, kalendář a informace o aktuálně vybrané osobě.

Prostřední část formuláře upomínače narozenin v Pythonu

Vytvoříme QHBoxLayout, který bude obsahovat jednotlivé BoxLayouty s widgety.

  • QHBoxLayout
    • QHBoxLayout
      • QListWidget
    • QVBoxLayout
      • QHBoxLayout
        • QLabel
        • QLabel
      • QHBoxLayout
        • QLabel
        • QLabel
      • QCalendarWidget
# Předchozí kód metody __init__() třídy PrehledForm
# ...

# Společný layout pro osobyListBox a narozenMonthCalendar
self.prostredniLayout = QtWidgets.QHBoxLayout()
layoutFormulare.addLayout(self.prostredniLayout)

# Vytvoříme layout pro osobyListBox
self.jmenaLayout = QtWidgets.QHBoxLayout()
self.osobyListBox = QtWidgets.QListWidget()
self.jmenaLayout.addWidget(self.osobyListBox)
self.prostredniLayout.addLayout(self.jmenaLayout)

# Vytvoříme layout pro narozenMonthCalendar
self.kalendarLayout = QtWidgets.QVBoxLayout()
self.narozenMonthCalendar = QtWidgets.QCalendarWidget(self)
self.narozenMonthCalendar.setEnabled(False)

# Vytvoříme layout pro informace o osobách
self.osobaLayout = QtWidgets.QHBoxLayout()
self.osobaLayout.addWidget(QtWidgets.QLabel("Narozen:"))
self.osobaLayout.addStretch()
self.narozeninyLabel = QtWidgets.QLabel("")
self.osobaLayout.addWidget(self.narozeninyLabel)
self.kalendarLayout.addLayout(self.osobaLayout)
self.osobaLayout2 = QtWidgets.QHBoxLayout()
self.osobaLayout2.addWidget(QtWidgets.QLabel("Věk:"))
self.osobaLayout2.addStretch()
self.vekLabel = QtWidgets.QLabel("")
self.osobaLayout2.addWidget(self.vekLabel)

self.kalendarLayout.addLayout(self.osobaLayout2)
self.kalendarLayout.addWidget(self.narozenMonthCalendar)
self.prostredniLayout.addLayout(self.kalendarLayout)

self.show()

Naše počínání je velmi podobné jako u informačního boxíku. Pro celou prostřední část jsme si vytvořili QHBoxLayout, aby se její součásti mohly řadit vedle sebe. Přidání QListWidget je triviální. Další widgety vpravo jsou komplikované jen kvůli layoutům. Je zde třeba vložit další QVBoxLayout, který umožní zobrazit dva layouty s labely a třetí s kalendářem pod sebou. U kalendáře je zajímavé patrně jen to, že jsme mu nastavili setEnabled(False), aby se na něm datum narození vybrané osoby zobrazovalo, ale nedalo se vybrat jiné.

Náš formulář PrehledForm je skoro hotov, stačí jen přidat tlačítka :)

Rozpracovaný přehledový formulář upomínače narozeniny v PyQt

Formuláře dokončíme v příští lekci, Upomínač narozenin v PyQt - Dokončení návrhu formulářů.


 

Stáhnout

Staženo 7x (6.11 kB)
Aplikace je včetně zdrojových kódů v jazyce Python

 

 

Článek pro vás napsal MQ .
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje Pythonu, tvorbě cross-platform aplikací a příležitostně webům, zajímá se o machine learning a celkově práci s daty.
Aktivity (4)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!