Pouze tento týden sleva až 80 % na e-learning týkající se Javy

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) layout
  • QLabel - Popisky
  • QLineEdit - Jednořádkové textové pole
  • QPlainTextEdit - Víceřádkové pole
  • QHBoxLayout - Ukážeme jak do gridu vložit jiné layouty
  • QPushButton - 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)
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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 48x (2.85 kB)
Aplikace je včetně zdrojových kódů v jazyce Python

 

Předchozí článek
Aplikace Kalkulačka v PyQt
Všechny články v sekci
PyQt - Okenní aplikace v Pythonu
Článek pro vás napsal Marek Bečvář
Avatar
Jak se ti líbí článek?
1 hlasů
Marek Bečvář
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í!