Search
Vzorové příklady najdete v repozitáři tutorials v adresáři tut07
tutorials
git pull cd tut07
Alternativně lze najít kódy také v archivu: ppc-tut07.zip
— Aktualizace 2020/04/14 22:44 - opraveny chyby, dodány chybějící soubory
QApplication app(argc, argv); QPushButton b1("Button 1"); b1.show(); return app.exec();
Mohlo by se zdát, že další komponentu lze přidat vytvořením nového objektu.
QPushButton b1("Button 1"); QPushButton b2("Button 2"); b1.show(); b2.show();
Chování výsledného programu je ale jiné: vytvořila se dvě okna (každé s voláním .show()) a okna se vzájemně překrývají.
.show()
Řešením je umístit komponenty na jinou vhodnou komponentu, která pak bude zobrazena. Pro tento účel se hodí instance třídy QWidget, která sama o sobě nemá žádnou grafickou podobu, ale může být rodičovským kontejnerem pro jiné objekty. Příslušnost komponenty k rodičovském kontejneru se vytváří vložením ukazatele na rodičovský objekt do konstruktoru komponenty.
QWidget
QWidget w; QPushButton b1("Button 1", &w); QPushButton b2("Button 2", &w); w.show();
Po spuštění přeloženého programu to na první pohled vypadá, že nedošlo k žádné změně. Okno je sice pouze jedno, komponenty (tlačítka) jsou ale přes sebe.
move()
resize()
QWidget w; w.resize(100,100); QPushButton b1("Button 1", &w); QPushButton b2("Button 2", &w); b2.move(0, 50); w.show();
Qt umožňuje pro stylování komponent využívat styly podobné kaskádovým stylům známým z HTML. Komponenty, které budeme používat, podporují box model.
QPushButton b1("Button 1", &w); b1.setStyleSheet("background-color: red;" "border-style: outset;" "border-width: 2px;" "border-radius: 10px;" "border-color: beige;" "font: bold 14px;" "min-width: 10em;" "padding: 6px;");
Absolutní pozicování widgetů je pochopitelně velmi nešikovné. Umožňuje sice mít absolutní kontrolu nad polohou komponent, ale i malé v podobě aplikace změny mohou znamenat velké změny v programu.
Qt pro pozicování komponent zavádí tzv. layouty, kontejnery, ve kterých je pozice vloženého widgetu řízena pravidlem. Následující příklad vykreslí 10 tlačítek uspořádaných horizontálně v komponentě QHBoxLayout. Opět je použita instance třídy QWidget jako rodičovský kontejner, jednotlivé komponenty jsou ale vkládány do layoutu a ten je pak kontejneru funkcí setLayout() přiřazen. Na rozdíl od absolutního pozicování je velikost rodičovského widgetu určena automaticky.
QWidget w; QHBoxLayout l; for (int i = 0; i < 10; i++) { QString name = QString("%1 %2").arg("button").arg(i); l.addWidget (new QPushButton (name)); } w.setLayout (&l); w.show();
V odstavci o stylování komponent jsme si ukázali, jak v kódu měnit styl GUI prvků. Pro skutečné programy je vhodné oddělit grafickou podobu aplikace a implementaci algoritmu. To je možné v případě stylování komponent v QT možné provést v styleSheet souboru, který je před spuštěním aplikace načten. Díky tomuto přístupu je možné hromadně stylovat celé třídy komponent (tj. instance tříd), specifické prvky podle názvu nebo podle atributu.
styleSheet
Aby qmake neměl problémy s hledánim souborů, které jsou v aplikaci použity (styly, obrázky, …), používá QT systém zdrojů. Cesty k použitým zdrojům jsou zapsány v .qrc souboru, který používá syntaxi založenou na XML. Příklad takové souboru:
qmake
.qrc
XML
<!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/"> <file>images/fig.png</file> <file>images/img.png</file> <file>styles/app.qss</file> </qresource> </RCC>
Soubor specifikuje, že zdroje aplikace jsou ve dvou adresářích, images a styles. Pokud chceme v aplikaci používat zdroje, je třeba je aktivovat voláním makra
images
styles
Q_INIT_RESOURCE(style); // cesta ke qrc souboru, bez přípony
K jednotlivým zdrojům lze pak přistupovat pomocí následující syntaxe
// načení stylesheetu ze souboru QFile styleSheet(":/styles/app.qss"); // aplikace stylesheetu app.setStyleSheet(styleSheet.readAll());
Základním způsobem, jak stylovat, je vytvoření stylu pro celou třídu
QAbstractButton { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(173,216,230,60%), stop:1 rgba(0,0,139,60%)); border-color: black; border-style: solid; border-width: 3px; border-radius: 6px; height: 50px; width: 50px; }
Tento styl zajistí, že všechny instance všech tříd, derivovaných ze třídy QAbstractButton budou vypadat stejně bez toho, aby bylo třeba v cpp kódu něco dalšího psát.
cpp
Pomocí pseudo stavů je možné zachytávat aktuální stav objektu a přizpůsobit mu grafickou podobou, zde např. změnit barvu při najetí myší na objekt:
QAbstractButton:hover { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(230,216,173,60%), stop:1 rgba(139,0,0,60%)); }
Pokud je třeba nastavit vlastnosti konkrétního prvku, lze využít selektoru jména
QAbstractButton#plus { background-color: none; background-image: url(:/files/add.png); } QAbstractButton#minus { background-color: none; background-image: url(:/files/remove.png); }
V cpp souboru pak přiřadíme jméno objektu
QPushButton b1; b1.setObjectName("minus");
Další možností je vytvoření atributu, který bude použit v metodě setProperty objektu. Přiřazení vlastnosti pak probíhá na základě hodnoty atributu.
QAbstractButton[odd=true] { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(173,216,230,60%), stop:1 rgba(0,0,139,60%)); } QAbstractButton[odd=false] { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(230,216,173,60%), stop:1 rgba(130,0,0,60%)); }
for (int i = 0; i < 12; i++) { QPushButton *b = new QPushButton; // ... b->setProperty("odd", (i%2) ? true : false); }