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.setCentralWidget(widget)
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.addWidget ( 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.
Hodnota aligment | Význam |
---|---|
QtCore.Qt.AlignLeft | Zarovná obsah doleva. |
QtCore.Qt.AlignRight | Zarovná obsah doprava. |
QtCore.Qt.AlignTop | Zarovná obsah nahoru. |
QtCore.Qt.AlignBottom | Zarovná obsah dolů. |
QtCore.Qt.AlignHCenter | Vycentruje obsah horizontálně. |
QtCore.Qt.AlignVCenter | Vycentruje obsah vertikálně. |
QtCore.Qt.AlignCenter | Vycentruje obsah vertikálně i horizontálně. |
Následující obrázky by měly pomoci k pochopení parametru stretch.
Hodnota stretch levého tlačítka je 0 a pravého 1.
Hodnota stretch levého tlačítka je 0 a pravého 0.
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.addWidget ( widget, stretch = 0, alignment = 0 )
Tato funkce funguje stejně jako QHBoxLayout.addWidget ( 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.addWidget ( widget, row, column, rowSpan, columnSpan, alignment = 0)
QGridLayout.addWidget ( 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
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í.