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 2 - Aplikace Kalkulačka v PyQt

V minulé lekci, Seznámení s PyQt, Instalace a první okenní aplikace v Python, jsme si udělali úvod do tvorby formulářových aplikací v Pythonu a naprogramovali okenní aplikaci Hello world.

Zdravím vás u další lekce PyQt. V dnešním tutoriálu si, jak bylo slibováno, vytvoříme aplikaci Kalkulačka, která bude provádět následující matematické operace:

  • součet
  • rozdíl
  • součin
  • podíl

Potřebné widgety

Pro lepší orientaci se můžete podívat na již hotový formulář:

Formulářová kalkulačka v Pythonu a PyQt - PyQt - Okenní aplikace v Pythonu

Aplikace bude obsahovat následující widgety:

  • QWidget - Formulář
  • QLabel - Popisek, zde použit na výpis výsledku
  • QPushButton - Tlačítko pro provedení výpočtu
  • 2x QLineEdit - Jednořádkové textové pole k zadání čísla
  • QComboBox - Rozbalovací nabídka s početními operacemi
  • Layouty - Abychom mohli widgety na formulář rozumně poskládat

Vytvoření projektu

Vytvořte nový projekt, já ten svůj uložím opět jako main.py. Nejprve si opět naimportujeme QWidgets z PyQt5 a sys. Dnes si naimportujeme také QtGui, protože dále změníme font našeho QLabelu s výsledkem.

from PyQt5 import QtWidgets, QtGui
import sys

Ačkoli jsme minule pracovali čistě procedurálně, bez objektů, jak jen jednoduše to šlo, je určitě lepší třídy pro své aplikace používat. Okno aplikace proto tentokrát vytvoříme jako třídu, dědící z QtWidgets.QMainWindow. Ukažme si její kód, který si záhy popíšeme:

class Window(QtWidgets.QMainWindow):

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

        self.setWindowTitle("Kalkulačka v PyQt5")
        self.init_gui()
        self.show()

    def init_gui(self):
        formular = QtWidgets.QWidget()

V konstruktoru si necháme předat případné argumenty z příkazové řádky a nastavíme titulek okna. Další inicializaci okna přenecháme metodě init_gui(). Nakonec formulář zobrazíme. V metodě init_gui() vytvoříme formulář jako minule a uložíme si jej do proměnné formular.

Layout

Celému formuláři nastavíme layout na QVBoxLayout, V v názvu označuje vertikální. Widgety na formuláři se budou tedy skládat pod sebe, na rozdíl od minulé lekce, kde jsme použili QHBoxLayout, kde H označovalo horizontální. Následně přidáme do tohoto svislého layoutu ještě 2 vodorovné layouty. Ty budou tedy pod sebou a widgety v nich vložené se budou skládat vedle sebe.

Kód metody init_gui() se rozroste do následující podoby:

def init_gui(self):
    formular = QtWidgets.QWidget()
    formularLayout = QtWidgets.QVBoxLayout()
    formular.setLayout(formularLayout)

    boxLayout1 = QtWidgets.QHBoxLayout()
    boxLayout2 = QtWidgets.QHBoxLayout()

    formularLayout.addStretch()
    formularLayout.addLayout(boxLayout1)
    formularLayout.addLayout(boxLayout2)
    formularLayout.addStretch()

Pokud jste se v layoutech ztratili, připravil jsem pro vás ilustraci:

Layouty formulářové kalkulačky v Pythonu a PyQt - PyQt - Okenní aplikace v Pythonu

formularLayout řadící widgety pod sebe je zvýrazněný červeně a layouty boxLayout1 a boxLayout2 v něm vložené, vkládající widgety vedle sebe, jsou vyznačené zeleně.

Pomocí addStretch() přidáme volné místo, které výsledek vycentruje svisle. Na obrázku výše je toto volné místo zvýrazněné modře.

Widgety

Máme hotové základní rozvržení naší aplikace, která je díky použití layoutů responzivní. To znamená, že když roztáhnete její okno, layouty se rovnoměrně roztáhnou s ním a widgety v nich se nové velikosti rovněž přizpůsobí. Nyní provedeme vložení dalších widgetů do layoutů:

def init_gui(self):
    formular = QtWidgets.QWidget()
    formularLayout = QtWidgets.QVBoxLayout()
    formular.setLayout(formularLayout)

    boxLayout1 = QtWidgets.QHBoxLayout()
    boxLayout2 = QtWidgets.QHBoxLayout()

    formularLayout.addStretch()
    formularLayout.addLayout(boxLayout1)
    formularLayout.addLayout(boxLayout2)
    formularLayout.addStretch()

    self.vysledekLabel = QtWidgets.QLabel("0", self)
    self.vysledekLabel.setFont(QtGui.QFont("Arial", 12, QtGui.QFont.Black))
    self.cislo1Edit = QtWidgets.QLineEdit(self)
    self.cislo2Edit = QtWidgets.QLineEdit(self)
    self.vypoctiButton = QtWidgets.QPushButton("Výpočet", self)
    self.operatorComboBox = QtWidgets.QComboBox(self)

    self.operatorComboBox.addItem("+")
    self.operatorComboBox.addItem("-")
    self.operatorComboBox.addItem("/")
    self.operatorComboBox.addItem("*")

    boxLayout1.addWidget(self.cislo1Edit)
    boxLayout1.addWidget(self.operatorComboBox)
    boxLayout1.addWidget(self.cislo2Edit)
    boxLayout1.addWidget(self.vysledekLabel)
    boxLayout2.addWidget(self.vypoctiButton)

    self.setCentralWidget(formular)

Vytváříme widgety, jejichž seznam jsme si uvedli v úvodu lekce. Do boxLayout1 vložíme textová políčka cislo1Edit a cislo2Edit, také operatorComboBox s výběrem operace a vysledekLabel. Všimněte si přidávání položek do operatorComboBox. Druhý řádek, boxLayout2, obsahuje jen vypoctiButton.

Widgety jsme pojmenovali tak, aby končily názvem PyQt widgetu. To je dobrá praktika, je tak jasné co je ve které proměnné uložené. Kdyby se vysledekLabel jmenoval jen vysledek, mohl by jiný programátor předpokládat, že se jedná jen o číslo a ne formulářový prvek.

Možná vás zaujalo, že některé widgety jsme uložili jen jako lokální proměnné a některé jsme uložili jako atributy třídy pomocí klíčového slova self. Je to proto, abychom s nimi mohli v aplikaci ještě dále pracovat.

Poslední metoda setCentralWidget() nastavuje náš formulář jako hlavní okno a tím se zobrazí po spuštění aplikace.

Na úplný konec souboru dodáme několik řádků s tvorbou a spuštění aplikace:

aplikace = QtWidgets.QApplication(sys.argv)
okno = Window()
sys.exit(aplikace.exec_())

Projekt si můžete nyní zkusit spustit, náš formulář vypadá takto:

Formulářová kalkulačka v Pythonu a PyQt - PyQt - Okenní aplikace v Pythonu

Zkuste si jej zmenšit a zvětšit, ať vidíte, že je opravdu responzivní.

Události

Nyní je třeba nastavit tlačítku vypoctiButton funkci, která se zavolá při události kliknutí na toto tlačítko. Těmto funkcím se v programování často říká callback. Danou funkci si zatím jen připravíme a na konci metody init_gui() ji navážeme na tlačítko.

def init_gui(self):
    # Předešlý kód metody init_gui() ...
    # ...

    self.vypoctiButton.clicked.connect(self.vypocti)

def vypocti(self):
    pass

# Zbytek souboru
# ...

Přidáme logiku naší metody vypocti():

def vypocti(self):
    vysledek = "";
    chyba = ""
    try:
        # do proměnných načteme hodnoty z ovládacích prvků
        cislo1 = float(self.cislo1Edit.text())
        cislo2 = float(self.cislo2Edit.text())
        operator = self.operatorComboBox.currentText()
        if (operator == "+"):
            vysledek = cislo1 + cislo2
        elif (operator == "-"):
            vysledek = cislo1 - cislo2
        elif (operator == "*"):
            vysledek = cislo1 * cislo2
        elif (operator == "/"):
            if (cislo2 == 0):
                chyba = "Chyba dělení 0"
            else:
                vysledek = cislo1 / cislo2
            else:
            chyba = "Chybná operace"
    except:
        # spustí se, pokud selže parsování na float()
        chyba = "Nebylo zadáno číslo!"
        if (chyba):
            self.vysledekLabel.setText(chyba) # zobrazení chyby
        else:
            self.vysledekLabel.setText(str(round(vysledek, 3))) # zobrazení výsledku zaokrouhleného na 3 desetinná místa

Nejprve si vytvoříme pomocné proměnné pro hodnoty, které načítáme z ovládacích prvků. To abychom dále neopisovali dlouhé názvy a volání dalších metod. Z QLineEdit získáme text pomocí metody text(). Vybranou položku QComboBox získáme metodou currentText(). Téměř celý kód je v bloku try, protože funkce float(), převádějící text z textových polí na číslo, může způsobit chybu. V takovém případě program přejde ihned do bloku except, chybu vypíše a výpočet se vůbec neprovede. Na samotném výpočtu není nic moc zajímavého, za zmínku stojí asi jen ošetření proti dělení nulou.

Máme hotovo :) Můžete si vyzkoušet, že kalkulačka opravdu počítá a hlásí případné chyby.

Hotová formulářová kalkulačka v PyQt pro Python - PyQt - Okenní aplikace v Pythonu

V příští lekci, GridLayout v PyQt - Formulář s využitím tabulky, využijeme QGridLayout pro jednoduchou tvorbu přehledných formulářů.


 

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 755x (3.66 kB)
Aplikace je včetně zdrojových kódů v jazyce Python

 

Předchozí článek
Seznámení s PyQt, Instalace a první okenní aplikace v Python
Všechny články v sekci
PyQt - Okenní aplikace v Pythonu
Přeskočit článek
(nedoporučujeme)
GridLayout v PyQt - Formulář s využitím tabulky
Článek pro vás napsal MQ .
Avatar
Uživatelské hodnocení:
58 hlasů
Používám hlavně Python a zajímám se o Deep Learning a vše kolem.
Aktivity