Předvánoční Black Friday Předvánoční Black Friday
Až 80% zdarma! Předvánoční BLACK FRIDAY akce. Více informací

Lekce 7 - PyQt - Kreslení na QWidget

Python Okenní aplikace PyQt - Kreslení na QWidget

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Upomínač narozenin v PyQt - Dokončení aplikace, jsme dokončili formulářovou aplikaci k upomínání narozenin. 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

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

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

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ženo 73x (2.53 kB)

 

 

Článek pro vás napsal MQ .
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor je srdcem Pythonista.
Aktivity (5)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!