IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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:

Aplikace pro evidenci kinosálu v PyQt a Pythonu - PyQt - Okenní aplikace v Pythonu

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ář:

Layout Python aplikace pro správu kinosálu - PyQt - Okenní aplikace v Pythonu

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:

Kinosál v Pythonu - PyQt - Okenní aplikace v Pythonu

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ínkami

Staženo 533x (2.53 kB)

 

Předchozí článek
Řešené úlohy k 4.-7. lekci PyQt
Všechny články v sekci
PyQt - Okenní aplikace v Pythonu
Přeskočit článek
(nedoporučujeme)
PyQt - Zpracování kliknutí na souřadnice
Článek pro vás napsal MQ .
Avatar
Uživatelské hodnocení:
14 hlasů
Používám hlavně Python a zajímám se o Deep Learning a vše kolem.
Aktivity