Lekce 3 - GridLayout v PyQt - Formulář s využitím tabulky
V minulé lekci, Aplikace Kalkulačka v PyQt, jsme si ukázali tvorbu jednoduché okenní kalkulačky. Vyzkoušeli jsme si callback funkce při stisknutí tlačítka a změnu hodnoty/textu u labelu.
V dnešním PyQt tutoriálu si ukážeme jak jednoduše pracovat s
umístěním widgetů do našich formulářů pomocí QGridLayout
.
Ten nám umožní vkládat prvky do pomyslné tabulky nebo
chcete-li mřížky.
Návrh formuláře
QGridLayout
se často používá např. pro formuláře, kde
jsou v jednom sloupci popisky a v druhém příslušná formulářová pole.
Tabulka zajistí, že je vše hezky zarovnané. Podobně bude vypadat i náš
dnešní formulář:
Tentokrát nám jde o to zkusit si jen nový layout, takže nebudeme vytvářet funkční aplikaci. Budeme potřebovat:
QWidget
- FormulářQGridLayout
- Náš tabulkový (grid) layoutQLabel
- PopiskyQLineEdit
- Jednořádkové textové poleQPlainTextEdit
- Víceřádkové poleQHBoxLayout
- Ukážeme jak do gridu vložit jiné layoutyQPushButton
- Tlačítka
Vytvoření formuláře
Vytvoříme si nový Python projekt.
Importy
Pro práci s PyQt si nejprve musíme naimportovat samotnou knihovnu
PyQt5
a knihovnu sys
:
from PyQt5 import QtWidgets, QtGui, QtCore import sys
Z PyQt5
nám QtWidgets
umožní pracovat s widgety,
díky QtGui
můžeme měnit fonty, které se ve formuláři budou
zobrazovat, a s QtCore
můžeme určit, kam se budou widgety a
texty v aplikaci zarovnávat.
Třída s formulářem
Dále si vytvoříme třídu Formular
. Objekty nám ulehčí jak
práci, tak přehlednost, proto se hodí jich využívat. Naše třída bude
dědit z třídy QtWidgets.QMainWindow
:
class Formular(QtWidgets.QMainWindow): def __init__(self, **kwargs): super(Formular,self).__init__(**kwargs) self.setWindowTitle("Formulář") self.setFixedSize(500,300) self.init_gui() self.show() def init_gui(self): """ Rozmístění formuláře """ formular = QtWidgets.QWidget()
Rovnou při vytváření si můžeme definovat jaký titulek a jaké rozměry bude naše aplikace mít.
Použití setFixedSize()
opravdu "fixuje" velikost
našeho okna. Tudíž tímto i zamezíme uživateli okno zvětšovat nebo
zmenšovat.
Zavoláním metody init_gui()
se přesuneme do naší další
funkce, kde si už nadefinujeme, jak bude formulář vypadat.
Práce s QGridLayout
Formuláři nastavíme layout na QGridLayout
. To nám zatím ve
formuláři nic nezmění, ale další widgety již budeme schopni vkládat do
gridu:
def init_gui(self): """ Rozmístění formuláře """ formular = QtWidgets.QWidget() grid = QtWidgets.QGridLayout() formular.setLayout(grid) self.setCentralWidget(formular) grid.setSpacing(10)
Zde si v proměnné grid
budeme udržovat odkaz na náš layout,
který následně nastavíme formuláři jako hlavní.
Funkce setSpacing(int)
nám umožní definovat, jak
daleko od sebe budou jednotlivé buňky v gridu. Nastavení hodnoty na
0
by tedy znamenalo, že dvě buňky vedle sebe budou mít
0
pixelů mezeru (což je často nečitelné).
Jak se v gridu vyznat?
Grid je vlastně jednoduchá tabulka s m
řádky a n
sloupci. Pokud tedy chceme
něco vložit na pozici v 1. řádku a 1. sloupci, budeme vkládat na index
(0
;0
). Počítáme od 0
podobně jako
indexování listů v Pythonu.
Ukažme si tabulku s pár sloupci a řádky a indexy jednotlivých buněk v ní:
0 | 1 | 2 | ... | n | |
---|---|---|---|---|---|
0 | (0,0) | (0,1) | (0,2) | ... | (0,n) |
1 | (1,0) | (1,1) | (1,2) | ... | (1,n) |
2 | (2,0) | (2,1) | (2,2) | ... | (2,n) |
... | ... | ... | ... | ... | ... |
m | (m,0) | (m,1) | (m,2) | ... | (m,n) |
Při vytváření formulářů nemusíme nikde dopředu specifikovat, jak velká má tato tabulka být. Grid se vytvoří až podle toho, na jaké indexy mu přiřadíme naše widgety.
Vkládání widgetů
Teď již k samotným widgetům, které budeme používat. Z obrázku můžeme vidět, že náš formulář bude mít 7 řádků a 3 sloupce:
V prvních šesti řádcích budou informace o osobě, kterou přidáváme. V sedmém potom tlačítka. Kód si proto rozdělíme do několika částí.
2 sloupce
Nejprve přidáme widgety do prvních dvou sloupců, tedy QLabel
a QLineEdit
:
def init_gui(self): """ Rozmístění formuláře """ formular = QtWidgets.QWidget() grid = QtWidgets.QGridLayout() formular.setLayout(grid) self.setCentralWidget(formular) grid.setSpacing(10) self.jmeno_text = QtWidgets.QLabel("Jméno:") self.jmeno_text.setFont(QtGui.QFont("Arial", 14)) grid.addWidget(self.jmeno_text, 0,0, QtCore.Qt.AlignRight) self.jmeno_input = QtWidgets.QLineEdit() self.jmeno_input.setFont(QtGui.QFont("Arial", 14)) self.jmeno_input.setAlignment(QtCore.Qt.AlignLeft) grid.addWidget(self.jmeno_input, 0,1, QtCore.Qt.AlignCenter)
Takto můžeme vytvořit první řádek formuláře. Vždy si nejdříve
pomocí QLabel
vytvoříme popisek řádku. Určíme font textu a
přidáme popisek do našeho grid
pomocí addWidget()
.
Zde určíme, jaký widget přidáváme, na jakou pozici, a navíc, pokud
chceme, určíme i zarovnání widgetu v buňce.
Můžeme si všimnout, že popisek prvního řádku se vkládá na pozici
(0,0)
. Textové pole, které k popisku patří, se pak vloží na
pozici (0,1)
.
Toto bychom mohli kód opakovat pro všechny řádky, které chceme nadefinovat. Takový zápis je ale zdlouhavý, ne tak přehledný a rozhodně se nám nelíbí kopírovat 7 řádků kódu všude po našem programu.
Generování řádků cyklem
Hezčí způsob je využít cyklu:
def init_gui(self): """ Rozmístění formuláře """ formular = QtWidgets.QWidget() grid = QtWidgets.QGridLayout() formular.setLayout(grid) self.setCentralWidget(formular) grid.setSpacing(10) texty = ["Jméno:", "Příjmení:", "Ulice:", "Město:", "Zip:", "Národnost:"] vstupy = [] for i in range(len(texty)): text = QtWidgets.QLabel(texty[i]) text.setFont(QtGui.QFont("Arial", 14)) grid.addWidget(text, i,0, QtCore.Qt.AlignRight) vstup = QtWidgets.QLineEdit() vstup.setFont(QtGui.QFont("Arial", 14)) vstup.setAlignment(QtCore.Qt.AlignLeft) grid.addWidget(vstup, i,1, QtCore.Qt.AlignCenter) vstupy.append(vstup)
Nejprve si vytvoříme list texty
všech popisků, které v
jednotlivých řádcích chceme. Poté si připravím nový prázdný list
vstupy
, do kterého uložíme odkazy na jednotlivá vytvořená
textová pole (to abychom s nimi mohli později pracovat, tedy číst z nich
text, atd.).
Poté již jen vytváříme cyklus, který se opakuje přes všechny prvky v
listu texty
. Vybraný text se použije jako popisek. Poslední
změna je určit, na jakou pozici budeme widgety vkládat, ale i to je lehké.
Řádek je index našeho cyklu.
Třetí sloupec
Teď přidáme i třetí sloupec. Zde chceme popisek a víceřádkové
textové pole, pro to využijeme QPlainTextEdit
:
def init_gui(self): # předchozí kód ... info_text = QtWidgets.QLabel("Info:") info_text.setFont(QtGui.QFont("Arial", 14)) grid.addWidget(info_text, 0,2, QtCore.Qt.AlignLeft) self.info_input = QtWidgets.QPlainTextEdit() self.info_input.setFont(QtGui.QFont("Arial", 14)) self.info_input.setFixedHeight(100) grid.addWidget(self.info_input, 0,2,4,1, QtCore.Qt.AlignCenter)
Přidání popisku je stejné, až na pozici. Jedná se o 1. řádek a 3.
sloupec, pozice tedy bude (0,2)
. Pro QPlainTextEdit
chceme, aby byl trochu vyšší, než ostatní textová pole. Pomocí
setFixedHeight()
mu můžeme nastavit výšku.
Při přidávání do gridu si všimneme, že vedle souřadnic pozice, kam
widget přidat, máme ještě další dvě souřadnice. Metoda
addWidget()
nám dovoluje specifikovat, na kolik
řádků/sloupců se má widget v tabulce
roztáhnout. Kdybychom toto roztažení nepoužili, mohlo by se
nám stát, že textové pole klidně překryje vlastní popisek. Takto se ale
roztáhne pod ním.
Řádek s tlačítky
Teď ještě poslední řádek s tlačítky. Zde chceme tři tlačítka vedle
sebe, která se vymykají našemu gridu. Využijeme proto již layout, který
byl použit v minulých lekcích a to QHBoxLayout
. Layouty
samozřejmě můžeme takto vhodně kombinovat:
def init_gui(self): # předchozí kód ... box = QtWidgets.QHBoxLayout() self.tlacitko_zpet = QtWidgets.QPushButton("Zpět") self.tlacitko_zpet.setFixedSize(80,40) box.addWidget(self.tlacitko_zpet) self.tlacitko_zrusit = QtWidgets.QPushButton("Zrušit") self.tlacitko_zrusit.setFixedSize(80,40) box.addWidget(self.tlacitko_zrusit) self.tlacitko_dalsi = QtWidgets.QPushButton("Další") self.tlacitko_dalsi.setFixedSize(80,40) box.addWidget(self.tlacitko_dalsi) grid.addLayout(box,6,0,1,3, QtCore.Qt.AlignRight)
Nejprve si vytvoříme QHBoxLayout
do proměnné
box
. Poté jednotlivá tlačítka postupně přidáváme do layoutu
box
. Když máme všechna tlačítka, můžeme si celý
box
přidat zpět do gridu pomocí addLayout()
. Opět
udáváme, že se box
může ve svém řádku roztáhnout přes
všechny 3 sloupce.
Takto jsme vytvořili celé GUI pro náš formulář!
Spuštění aplikace
Na úplný konec programu už jen přidáme pár řádek pro spuštění aplikace:
aplikace = QtWidgets.QApplication(sys.argv) okno = Formular() sys.exit(aplikace.exec_())
A výsledek:
V následujícím cvičení, Řešené úlohy k 1.-3. lekci PyQt, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 176x (2.85 kB)
Aplikace je včetně zdrojových kódů v jazyce Python