Lekce 8 - PyQt - Kreslení na QWidget
V předešlém cvičení, Řešené úlohy k 4.-7. lekci PyQt, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V našich aplikacích se nám občas stane, že kromě standardních
tlačítek, listů a labelů, budeme potřebovat něco vykreslit. Kreslení se
budeme věnovat právě v dnešním Python tutoriálu. Vykreslíme si kinosál
na QWidget za pomoci QPainter.
Kreslení na widgety
Pro kreslení na PyQt widget využíváme metodu
paintEvent(self, event), která se automaticky volá ve chvílích,
kdy se formulář překresluje. To je nejen když se formulář vykreslí
poprvé, ale i když byl např. překryt jiným oknem, které bylo náhle
přesunuto, a měl by se tedy opět překreslit. Událost má dva parametry, jak
je v Pythonu zvykem. Prvním z nich je instance
(self/parent) a druhým je samotná událost, ze
které se dají v případě potřeby získat další data.
Základní struktura aplikace
Vytvoříme QWidget, kterému nastavíme
QVBoxLayout layout. Přidáme také tlačítko, které bude
sloužit pro ukládání informací o tom, jaká sedadla jsou obsazená.
Pro lepší představu si ukažme výslednou aplikaci:

Vytvořte si nový projekt, já jsem soubor pojmenoval
kinosal.py.
Importy
Na začátek souboru si nezapomeňte přidat následující importy:
from PyQt5 import QtWidgets, QtGui, QtCore import sys
Dále přidáme následující kód pro založení formuláře a aplikace:
class Window(QtWidgets.QMainWindow): def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() widget.setLayout(layout) self.setCentralWidget(widget) button = QtWidgets.QPushButton("Uložit") layout.addStretch() layout.addWidget(button) self.show() class App(QtWidgets.QApplication): def build(self): self.window = Window() sys.exit(self.exec_()) app = App(sys.argv) app.build()
Jedná se pouze o základní kostru, kterou jsme tu již několikrát vytvářeli a nemělo by vás v ní již nic překvapit. Aplikaci si můžete zkusit spustit, zatím získáte takovýto jednoduchý formulář:

Logická vrstva
Asi vás nepřekvapí, že budeme pokračovat vytvořením třídy
Kinosal. V té bude list sedadla s hodnotami
True/False. Dále bude obsahovat velikost
sedadla na obrazovce a velikost mezery mezera v pixelech. Tyto
atributy budeme využívat při kreslení. Následující kód třídy si
vložte nad třídu App:
class Kinosal: # vytvoříme list 30 je šířka a 15 jeho výška sedadla = [[False for i in range(15)] for i in range(30)] velikost = 16 mezera = 2
Určitě jste si všimli, že list je dvourozměrný. Jak pracovat s dvourozměrnými poli jsme si vysvětlovali v lekci Vícerozměrná pole v Pythonu. V paměti jsme vytvořili 2d pole 30 x 15 sedadel.
Abychom se do kinosálu dostali ze všech míst naší aplikaci, vytvoříme
jeho instanci ve třídě App a uložíme ji stejně, jako jsme to
dělali s formuláři a manažery v předešlé aplikaci k upomínání
narozenin:
class App(QtWidgets.QApplication): def build(self): self.kinosal = Kinosal() self.window = Window() sys.exit(self.exec_())
Vykreslení
Jak jsem zmínil v úvodu, budeme potřebovat metodu
paintEvent(), jelikož kreslíme na widget. Tu do třídy
Window dodáme. Rovnou aktualizujeme i konstruktor, který nastaví
takovou velikost formuláře, aby se do něj jednotlivá sedadla a mezery mezi
nimi vešly. Celý kód třídy Window nyní vypadá
následovně:
class Window(QtWidgets.QMainWindow): def __init__(self, *args, **kwargs): super(Window, self).__init__(*args, **kwargs) self.resize((app.kinosal.velikost + app.kinosal.mezera) * len(app.kinosal.sedadla), (app.kinosal.velikost + app.kinosal.mezera) * len(app.kinosal.sedadla[0]) + 80) widget = QtWidgets.QWidget() layout = QtWidgets.QVBoxLayout() widget.setLayout(layout) self.setCentralWidget(widget) button = QtWidgets.QPushButton("Uložit") layout.addStretch() layout.addWidget(button) self.show() def paintEvent(self, event): p = QtGui.QPainter(self) for j in range(len(app.kinosal.sedadla[0])): for i in range(len(app.kinosal.sedadla)): if app.kinosal.sedadla[i][j]: #Nastavíme červenou barvu barva = QtCore.Qt.red else: #Nastavíme zelenou barvu barva = QtCore.Qt.green velikostSMezerou = app.kinosal.velikost + app.kinosal.mezera p.fillRect(i * velikostSMezerou, j * velikostSMezerou, app.kinosal.velikost, app.kinosal.velikost, QtGui.QBrush(barva)) p.end()
V metodě paintEvent() používáme instanci
QPainter. Ta obsahuje metodu pro vykreslení základních
geometrických tvarů a textu. Jednotlivá sedadla kinosálu kreslíme za pomoci
fillRect(x, y, w, h, QBrush). Jak asi tušíte, metoda
fillRect() vykreslí vyplněný obdélník. Jednotlivé barvy
nalezneme jako vlastnosti na třídě QtCore.Qt. Všimněte si, že
obsazeným sedadlům s hodnotou True nastavujeme červenou barvu,
jinak nastavujeme barvu zelenou. Vykreslení jednotlivých obdélníků
(sedadel) samozřejmě probíhá ve 2 vnořených cyklech, kdy první
projíždí sloupce a druhý řádky.
Náš výsledek vypadá zatím takto:

V příští lekci, PyQt - Zpracování kliknutí na souřadnice, naprogramujeme klikání na sedadla pomocí myši a ukládání obsazenosti sedadel do souboru.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkamiStaženo 747x (2.53 kB)

