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