Hlavní navigace

PyQt4: Layouty, signály a sloty

Jan Kaluža

V dnešním, v pořadí druhém, díle seriálu o PyQt si povíme o layoutech, které nám pomůžou s rozmístěním widgetů v okně naší příkladové aplikace. Také si vysvětlíme používání signálů a slotů, které jsou jedním ze základních stavebních prvků PyQt4. Povíme si i o funkcích, které se při práci se signály a sloty nejvíce používají.

Signály a sloty – Teorie

Každý objekt v Qt4 má nějaké své signály a sloty. Signály, jak již jejich název napovídá, jsou zprávy, které objekt generuje v případě jeho změny nebo při nějaké důležité události (typickým signálem může být například kliknutí myší na tlačítko). Každý signál může být napojen na slot. Slot je pro změnu klasická funkce, která, pokud je připojena k signálu, je zavolána a umožňuje nějakým způsobem měnit objekt. Slotem může být i funkce v Pythonu. Nyní si povíme o funkcích, které se při práci se signály a sloty nejvíce používají.

SIGNAL ( signal ) – modul QtCore

Funkce SIGNAL přijímá jako svůj jediný parametr jméno signálu v podobě textu. Text převádí do tvaru, kterému rozumí funkce connect, se kterou se tato funkce využívá. Typickým signálem může být signál „clicked()“, který je generován tlačítkem při kliknutí na něj.

QObject.connect ( sender, signal, method )

Tato funkce připojí signál (parametr signal), který je vygenerovaný objektem sender na funkci (metodu) method. Jinak řečeno, pokud vygeneruje sender signál signal, je spuštěna funkce (metoda) method. Proměnná signal je vytvořena pomocí funkce SIGNAL, o které jsme se bavili výše. Pokud bychom tedy chtěli tlačítko z minulého dílu napojit na nějakou funkci pythonu, kterou jsme sami definovali, můžeme tak učinit tímto kódem:

# deklarujeme funkci, na kterou chceme napojit signal
def moje_funkce():
   print "ahoj svete"
# Napojime signal "clicked()" tlacitka PushButton na nasi funkci moje_funkce()
app.connect(PushButton,QtCore.SIGNAL("clicked()"),moje_funkce)

Jen pro úplnost dodávám, že funkci connect předáváme pouze „ukazatel“ na naši funkci moje_funkce(), a proto se do zápisu nepíší závorky. Obdobným způsobem můžeme napojit signál jednoho Qt4 objektu na slot jiného Qt4 objektu. Představme si, že chceme po kliknutí na tlačítko zavřít naše okno. K uzavření okna použijeme jeho slot „close()“. Příkaz pro napojení signálu na slot pak bude vypadat takto:

# Napojime signal "clicked()" tlacitka PushButton na slot close okna MainWindow
app.connect(PushButton,QtCore.SIGNAL("clicked()"),MainWindow.close)

Signály a sloty – Praxe

Náš program z minulého dílu vylepšíme o možnost zavřít jej kliknutím na tlačítko. V podstatě do něj jen vložíme kód, který jsme si vysvětlili v teoretické části. Celý program pak bude vypadat takto:

from PyQt4 import QtCore, QtGui
import sys

app = QtGui.QApplication(sys.argv)

MainWindow = QtGui.QMainWindow()
MainWindow.setWindowTitle("Titulek okna")

PushButton = QtGui.QPushButton(MainWindow)
PushButton.setText("Popisek tlacitka")

# Napojime signal "clicked()" tlacitka PushButton na slot close okna MainWindow
app.connect(PushButton,QtCore.SIGNAL("clicked()"),MainWindow.close)

MainWindow.show()
sys.exit(app.exec_())

Layouty – Teorie

Layout je mřížka či tabulka, do které můžeme umísťovat Qt4 objekty (widgety). Důležitou vlastností layoutu je to, že mění svoji velikost společně s oknem (nebo jiným nadřazeným objektem), takže s použitím layoutu se budou objekty uvnitř okna dynamicky zvětšovat a zmenšovat podle toho, jak velké okno bude. Jediným problémem spojeným s layouty je to, že nemůže být přidán přímo do hlavního okna (QMainWindow). Hlavní okno totiž již obsahuje interní layout, který se stará o zarovnání případných toolbarů nebo nabídek. Layout tedy musíme vložit do prázdného objektu (widget), který vytvoříme funkcí QWidget(). Dále musíme nastavit tento prázdný widget jako centrální widget naší aplikace, což provedeme funkcí setCentralWidget. Nyní si již můžeme popsat všechny funkce a s nimi i tři nejčastěji používané typy layoutů.

QWidget ( parent ) – modul QtGui

Vytvoří prázdný widget s rodičem parent.

QMainWindow.set­CentralWidget(wid­get)

Určí hlavní widget (objekt) okna.

QHBoxLayout ( parent ) – modul QtGui

Funkcí QHBoxLayout() vytvoříme layout, ve kterém se objekty budou řadit horizontálně. Parametr parent je nadřazeným objektem layoutu.

QHBoxLayout.ad­dWidget ( widget, stretch = 0, alignment = 0 )

Funkce přidá do layoutu nový widget, který je definován parametrem widget, na poslední místo v layoutu. Parametr stretch slouží k nastavení rozpínání widgetů v layoutu, pokud roztahujeme okno. Čím větší bude hodnota parametru stretch jednoho widgetu oproti ostatním, tím více se při zvětšování okna bude widget zvětšovat na úkor ostatních widgetů v layoutu. Parametr alignment nastavuje zarovnání widgetu v layoutu. Hodnoty, které může parametr alignment obsahovat jsou uvedeny v následující tabulce.

Hodnoty parametru alignment
Hodnota aligment Význam
QtCore.Qt.AlignLeft Zarovná obsah doleva.
QtCore.Qt.Alig­nRight Zarovná obsah doprava.
QtCore.Qt.AlignTop Zarovná obsah nahoru.
QtCore.Qt.Alig­nBottom Zarovná obsah dolů.
QtCore.Qt.Alig­nHCenter Vycentruje obsah horizontálně.
QtCore.Qt.Alig­nVCenter Vycentruje obsah vertikálně.
QtCore.Qt.Alig­nCenter Vycentruje obsah vertikálně i horizontálně.

Následující obrázky by měly pomoci k pochopení parametru stretch.

PyQt2 1

Hodnota stretch levého tlačítka je 0 a pravého 1.

PyQt2 2

Hodnota stretch levého tlačítka je 0 a pravého 0.

PyQt2 3

Hodnota stretch levého tlačítka je 1 a pravého 2.

QVBoxLayout ( parent ) – modul QtGui

Funkcí QVBoxLayout() vytvoříme layout, ve kterém se objekty budou řadit vertikálně. Parametr parent je nadřazeným prvkem layoutu.

QVBoxLayout.ad­dWidget ( widget, stretch = 0, alignment = 0 )

Tato funkce funguje stejně jako QHBoxLayout.ad­dWidget ( widget, stretch = 0, alignment = 0 ).

QGridLayout ( parent ) – modul QtGui

Funkce QGridLayout() vytváří layout, který si můžeme představit jako tabulku nebo mřížku. Můžeme si vybrat, do kterého sloupce a řádku widget umístíme a nastavit, přes kolik řádků a sloupců bude widget zobrazen.

QGridLayout.ad­dWidget ( widget, row, column, rowSpan, columnSpan, alignment = 0)
QGridLayout.ad­dWidget ( widget, row, column, alignment = 0 )

Funkce přidá do layoutu widget definovaný parametrem widget. Vloží jej do řádku row a sloupce column. Parametr ColumnSpan udává počet sloupců, přes které bude widget zobrazen, a parametr rowSpan udává počet řádků přes které se widget zobrazí. Nesmíme zapomenout na to, že první buňka se nachází v sloupci s indexem 0 a řádkem s indexem 0. Parametr alignment má stejný význam jako u ostatních layoutů. V případě, že chceme widget zobrazit pouze v jedné buňce, můžeme použít druhou možnou syntaxi, které vynechává parametry rowSpan a columnSpan.

Layouty – Praxe

PyQt2 4

V praxi si ukážeme pouze QGridLayout. Z ukázky by však mělo být jasné i použití zbylých dvou layoutů. Vytvoříme tři tlačítka. První dvě zobrazíme v jednom řádku vedle sebe. Jedno z nich zarovnáme doleva a druhé doprava. Třetí tlačítko zobrazíme pod nimi a roztáhneme jej přes dva sloupce. Pro procvičení doporučuji například zkusit dát tlačítka do jiného layoutu nebo napojit signály tlačítek na nějaké funkce.

from PyQt4 import QtCore, QtGui
import sys

app = QtGui.QApplication(sys.argv)

MainWindow = QtGui.QMainWindow()
MainWindow.setWindowTitle("Titulek okna")
# Vytvorime hlavni prazdny widget MainWidget s rodicem MainWIndow
MainWidget=QtGui.QWidget(MainWindow)
# Nastavime prazdny widget MainWidget jako centralni widget okna
MainWindow.setCentralWidget(MainWidget)

# Vytvorime QGridLayout
layout=QtGui.QGridLayout(MainWidget)

# Vytvorime tri tlacitka s rodicem MainWidget
Button1 = QtGui.QPushButton("Tlacitko 1",MainWidget)
Button2 = QtGui.QPushButton("Tlacitko 2",MainWidget)
Button3 = QtGui.QPushButton("Tlacitko 3",MainWidget)

# Pridame Button1 do prvniho radku prvniho sloupce a zarovname vlevo
layout.addWidget (Button1,0,0,QtCore.Qt.AlignLeft)
# Pridame Button2 do prvniho radku druheho sloupce a zarovname vpravo
layout.addWidget (Button2,0,1,QtCore.Qt.AlignRight)
# Pridame Button3 do druheho radku prvniho sloupce a to tak,
# ze bude v jednom radku, ale pres dva sloupce.
layout.addWidget (Button3,1,0,1,2)

MainWindow.show()
sys.exit(app.exec_())

Závěr

Další díl bude zaměřen hlavně na widget pro editovaní textu QLineEdit a textový popisek QLabel. Díky nim budeme moci udělat program více interaktivní.

Našli jste v článku chybu?

27. 1. 2007 10:25

hollees (neregistrovaný)
ja mel instalaci uplne bez problemu:
1. downloads a instalace:
python-2.5.msi
PyQt-gpl-4.1.1-Py2.5-Qt4.2.2.exe
qt-win-opensource-4.2.2-mingw.exe
sip-4.5.2.zip
(nekde v helpech bylo ze nedoporucuji instalovat qt do "program files")

2. pridat do promenne prostredi PATH cesty k mingw\bin, qt\bin a pythonu

3. prelozeni sip:
python configure.py -p win32-g++
make
make install

a melo by to valit














19. 1. 2007 19:53

Tak se mi to podařilo;-). Výsledek zde. Musel jsem trochu změnit postup, víc se kompiluje, ale zato to funguje.
DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Vitalia.cz: Taky věříte na pravidlo 5 sekund?

Taky věříte na pravidlo 5 sekund?

Měšec.cz: Sleva na dítě a manželku pro OSVČ je zpět. Ale..

Sleva na dítě a manželku pro OSVČ je zpět. Ale..

120na80.cz: Co všechno ovlivňuje ženskou plodnost?

Co všechno ovlivňuje ženskou plodnost?

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Vitalia.cz: Jmenuje se Janina a žije bez cukru

Jmenuje se Janina a žije bez cukru

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

DigiZone.cz: Sat novinky: slovenská TV8 HD i ruský NTV Mir

Sat novinky: slovenská TV8 HD i ruský NTV Mir

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

Podnikatel.cz: Udávání a účtenková loterie, hloupá komedie

Udávání a účtenková loterie, hloupá komedie

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání