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 669x (2.53 kB)