Chci geek triko! Chci geek triko!
Extra 10 % bodů navíc a tričko zdarma při zadání kódu "TRIKO10"

Lekce 2 - Aplikace Kalkulačka v PyQt

Python Okenní aplikace Aplikace Kalkulačka v PyQt

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.

Zdravím vás u další lekce PyQt. V lekci minulé, 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í Hello world. 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

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

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

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

V příští lekci, Upomínač narozenin v PyQt - Návrh formulářů, na nás čeká další projekt, tentokrát mnohem většího rozsahu. Nechte se překvapit :)


 

Stáhnout

Staženo 56x (3.66 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?
1 hlasů
Autor je srdcem Pythonista.
Aktivity (4)

 

 

Komentáře

Avatar
czech.freak
Člen
Avatar
czech.freak:28. června 21:56

Dík za pěkně zpracovaný díl. Vytvořit miniaplikaci v Pythonu a Qt je krásně jednoduché:-)

 
Odpovědět  +1 28. června 21:56
Avatar
Jiří Forst
Člen
Avatar
Jiří Forst:27. srpna 15:45

Čauky, lámu si hlavu, jak dostat výsledek výpočtu třeba 3+3 do Entry.
Ne objektově. Moc Díky

 
Odpovědět 27. srpna 15:45
Avatar
MQ .
Redaktor
Avatar
Odpovídá na Jiří Forst
MQ .:27. srpna 18:14

Zdravím, Entry nastavíš hodnotu takto muj_entry.insert(0, muj_text) (první argument je pozice kurzoru). Na zobrazení výsledku bych spíše použil Label, u kterého nastavíš text takto muj_label.config(text = muj_text).

Odpovědět 27. srpna 18:14
Programovácí jazyk zítřka bude vysokoúrovňový, bez ";", prostý a v neposlední řadě čitelný.
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.

Zobrazeno 3 zpráv z 3.