IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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

V předešlém cvičení, Řešené úlohy k 1.-3. lekci PyQt, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

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 - PyQt - Okenní aplikace v Pythonu

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 - PyQt - Okenní aplikace v Pythonu

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 - PyQt - Okenní aplikace 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 - PyQt - Okenní aplikace 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 - PyQt - Okenní aplikace v Pythonu

V další lekci, Upomínač narozenin v PyQt - Dokončení návrhu formulářů, rozpracujeme návrh prvního z formulářů aplikace v PyQt pro upomínání narozenin osob.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

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

 

Předchozí článek
Řešené úlohy k 1.-3. lekci PyQt
Všechny články v sekci
PyQt - Okenní aplikace v Pythonu
Přeskočit článek
(nedoporučujeme)
Upomínač narozenin v PyQt - Dokončení návrhu formulářů
Článek pro vás napsal MQ .
Avatar
Uživatelské hodnocení:
26 hlasů
Používám hlavně Python a zajímám se o Deep Learning a vše kolem.
Aktivity