Warning
This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

7. QT - úvod

Vzorové příklady najdete v repozitáři tutorials v adresáři tut07

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

Aplikace s jednou komponentou

QApplication app(argc, argv);
QPushButton b1("Button 1");
b1.show();
 
return app.exec();

Vložení více komponent

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í.

Ř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 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.

Komponenty (widgety) lze absolutně pozicovat metodou move() a měnit jejich velikost metodou resize().

QWidget w;
w.resize(100,100);
QPushButton b1("Button 1", &w);
QPushButton b2("Button 2", &w);
b2.move(0, 50);
w.show();

Úkoly

  1. Doplňte do aplikace další potomky abstraktní třídy QAbstractButton - QCheckBox a QRadioButton
  2. Nakreslete šachovnici 8×8 tlačítek

Stylování komponent

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;");

Úkol

  1. Upravte šachovnici z tlačítek tak, aby vypadala jako opravdová šachovnice

Layouty

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();

Správa zdrojů

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.

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:

<!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

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.

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);
}

courses/b2b99ppc/tutorials/07.txt · Last modified: 2020/04/14 22:46 by viteks