7. diel - PyQt - Kreslenie na QWidget
V minulej lekcii, PRIPOMIENKOVÉ narodenín v PyQt - Dokončenie aplikácie , sme dokončili formulárové aplikácii k
upomínania narodenín. V našich aplikáciách sa nám občas stane, že okrem
štandardných tlačidiel, listov a labelov, budeme potrebovať niečo
vykresliť. Kreslenie sa budeme venovať práve v dnešnom Python tutoriálu.
Vykreslíme si kinosála na QWidget za pomoci
QPainter.
Kreslenie na widgety
Pre kreslenie na PyQt widget využívame metódu
paintEvent(self, event), ktorá sa automaticky volá vo chvíľach,
keď sa formulár prekresľuje. To je nielen keď sa formulár vykreslí
prvýkrát, ale aj keď bol napr. Prekrytý iným oknom, ktoré bolo náhle
presunuté, a mal by sa teda opäť prekresliť. Udalosť má dva parametre, ako
je v Pythone zvykom. Prvým z nich je inštancie (self /
parent) a druhým je samotná udalosť, z ktorej sa dajú v
prípade potreby získať ďalšie dáta.
Základná štruktúra aplikácie
Vytvoríme QWidget, ktorému nastavíme QVBoxLayout
layout. Pridáme tiež tlačidlo, ktoré bude slúžiť na ukladanie
informácií o tom, aké sedadlá sú obsadené.
Pre lepšiu predstavu si ukážme výslednú aplikáciu:

Vytvorte si nový projekt, ja som súbor pomenoval
kinosal.py.
Importy
Na začiatok súboru si nezabudnite pridať nasledujúce importy:
from PyQt5 import QtWidgets, QtGui, QtCore import sys
Ďalej pridáme nasledujúci kód pre založenie formuláre a aplikácie:
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á sa len o základnú kostru, ktorú sme tu už niekoľkokrát vytvárali a nemalo by vás v nej už nič prekvapiť. Aplikáciu si môžete skúsiť spustiť, zatiaľ získate takýto jednoduchý formulár:

Logická vrstva
Asi vás neprekvapí, že budeme pokračovať vytvorením triedy
Kinosal. V tej bude list sedadla s hodnotami
True / False. Ďalej bude obsahovať
velikost sedadla na obrazovke a veľkosť medzery
mezera v pixeloch. Tieto atribúty budeme využívať pri
kreslení. Nasledujúci kód triedy si vložte nad triedu 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čite ste si všimli, že list je dvojrozmerný. Ako pracovať dvojrozmerných poli sme si vysvetľovali v lekcii Viacrozmerná poľa v Pythone. V pamäti sme vytvorili 2d pole 30 x 15 sedadiel.
Aby sme sa do kinosály dostali zo všetkých miest našej aplikácii,
vytvoríme jeho inštanciu v triede App a uložíme ju rovnako, ako
sme to robili s formulármi a manažérmi v predošlej aplikácii k upomínania
narodenín:
class App(QtWidgets.QApplication): def build(self): self.kinosal = Kinosal() self.window = Window() sys.exit(self.exec_())
Vykreslenie
Ako som spomenul v úvode, budeme potrebovať metódu
paintEvent(), keďže kreslíme na widget. Tú do triedy
Window dodáme. Rovno aktualizujeme aj konštruktor, ktorý
nastaví takú veľkosť formuláre, aby sa do neho jednotlivé sedadlá a
medzery medzi nimi vošli. Celý kód triedy Window teraz vyzerá
nasledovne:
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 metóde paintEvent() používame inštanciu
QPainter. Tá obsahuje metódu pre vykreslenie základných
geometrických tvarov a textu. Jednotlivé sedadlá kinosály kreslíme za
pomoci fillRect(x, y, w, h, QBrush). Ako asi tušíte, metóda
fillRect() vykreslí vyplnený obdĺžnik. Jednotlivé farby
nájdeme ako vlastnosti na triede QtCore.Qt. Všimnite si, že
obsadeným sedadlám s hodnotou True nastavujeme červenú farbu,
inak nastavujeme farbu zelenú. Vykreslenie jednotlivých obdĺžnikov
(sedadiel) samozrejme prebieha v 2 vnorených cykloch, keď prvý prechádza
stĺpce a druhý riadky.
Náš výsledok vyzerá zatiaľ takto:

V budúcej lekcii, Riešené úlohy k 3.-6. lekciu PyQt , naprogramujeme klikanie na sedadlá pomocou myši a ukladanie obsadenosti sedadiel do súboru.
V nasledujúcom cvičení, Riešené úlohy k 3.-6. lekciu PyQt, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 744x (2.53 kB)
