Stručný průvodce vytvářením GUI v C++/Qt Eduard Sojka URO, Léto 2004/5 VŠB – Technická univerzita Ostrava
Co je Qt? Qt: stručný průvodce Qt je knihovna prvků GUI existující na různých platformách (MS-Windows, Unix/Linux, Mac OS X). Používá ze z C++. Je hodnocena jako velmi dobrá. Pro vizuální konstruování existuje Qt Designer. Do Qt se uvedeme prostřednictvím jednoduchého příkladu. Jeho kompletní zdrojový text naleznete v souboru priklady_Qt\priklad1.cpp.
Qt: stručný průvodce – hlavní program Hlavní program vypadá v C++/Qt vždy podobně, jak je uvedeno dole. Je nutné zřídit objekt třídy QApplication a vyvolat metodu exec. Dále je potřebné připravit prvek GUI, který je považován za hlavní. Ten je často instancí třídy odvozené z QMainWindow. int main( int argc, char **argv ){ QApplication application( argc, argv ); MainWindow mainWindow; application.setMainWidget( &mainWindow ); mainWindow.show(); return application.exec(); }
Qt: stručný průvodce – hlavní okno GUI Konstrukce okna pomocí třídy odvozené z QMainWindow. Do oka je možné umístit „menu bar“, „tool bar“ a „status bar“. V centrální ploše lze umístit buď vlastní prvek (náš případ) nebo některé prvky standardní, např. QTextEdit nebo QCanvas. Aplikace může mít více oken odvozených z QMainWindow.
Qt: stručný průvodce – konstrukce hlavního okna MainWindow::MainWindow( ):QMainWindow( ){ setCaption( "URO - Qt" ); QPixmap *appIcon = new QPixmap( ); if( appIcon->load("mondrian.bmp")) setIcon(*appIcon); QMenuBar *menuBar = new QMenuBar( this ); // Tady naplnit menu. QToolBar *toolBar = new QToolBar( this ); // Tady naplnit toolBar. centralWidget = new CentralWidget( this ); setCentralWidget( centralWidget ); // Tridu CentralWidget popiseme dale. QStatusBar *statusBar = new QStatusBar( this ); statusBar->message( "The actions will appear here." ); } Typickými akcemi v konstruktoru hlavního okna jsou příprava menu, „tool bar“, „status bar“ a jejich zaregistrování.
Qt: stručný průvodce - menu QMenuBar *menuBar = new QMenuBar( this ); QPopupMenu *fileMenu = new QPopupMenu( this ); fileMenu->insertItem( QPixmap( fileopen_xpm ), "&Open", this, SLOT( onOpen() ), CTRL+Key_O ); … idMenuItem = fileMenu->insertItem( "&Another item", this, SLOT( onOtherAction() ) ); fileMenu->insertSeparator(); fileMenu->insertItem( "E&xit", qApp, SLOT( quit() ), CTRL+Key_X ); menuBar->insertItem( "File", fileMenu ); fileMenu->setItemEnabled( idMenuItem, false ); V jednotlivých položkách menu se uvádí mimo jiné, který objekt (zde this) a která metoda má na aktivaci položky reagovat. Musíme tedy vytvořit metody onOpen, … , onOtherAction. Qt používá termínu „slots“. Ikona „Open“ je definována v poli fileopen_xpm (definici naleznete v souboru fileopen.xpm).
Qt: stručný průvodce – „toolbar“ QToolBar *toolBar = new QToolBar( this ); toolBar->setLabel( "URO" ); toolBar->addSeparator(); QToolButton *fileOpenToolButton = new QToolButton( QPixmap( fileopen_xpm ), "Open", QString::null, this, SLOT( onOpen() ), toolBar ); QToolButton *measureLengthButton = new QToolButton( QPixmap( measurelength_xpm ), "Measure length", QString::null, this, SLOT( onMeasuringLength() ), toolBar ); Do „toolbar“ se obvykle umisťují tlačítka. Ta mohou mít nápovědu. Lištu „tool bar“ lze z okna vysunout. Opět je pro jednotlivá tlačítka specifikováno, který objekt (zde this) a kterou metodou je obsluhuje (SLOT).
Qt: stručný průvodce – konstrukce centrálního panelu Prvky zde skládáme pod sebe pomocí formátovače QVBoxLayout. Ten umí pod sebe přidávat buď samotné prvky (addWidget) nebo jejich naformátované sestavy (addLayout). Prvky a sestavy musíme předem připravit. Hodnoty 8 a 6 udávají požadovaný okraj a vzdálenost mezi prvky. Metoda addSpacing vkládá mezeru navíc. V konstruktoru centrálního panelu proto budeme mít: setPaletteBackgroundColor( QColor( 225, 225, 220 )); QVBoxLayout *topLayout = new QVBoxLayout( this, 8, 6 ); topLayout->addWidget( label1, 0, Qt::AlignCenter ); topLayout->addLayout( imageRow ); topLayout->addSpacing( 6 ); topLayout->addWidget( label3 ); topLayout->addWidget( textEdit ); topLayout->addWidget( checkGroup ); topLayout->addSpacing( 4 ); topLayout->addLayout( buttonRow );
Qt: stručný průvodce – konstrukce centrálního panelu Dále probereme konstrukci jednotlivých prvků, jejichž existenci jsme předpokládali v předchozím obrázku. Prvky budeme vytvářet v konstruktoru centrálního panelu (CentralWidget). Konstrukce prvku label1 je průhledná. Rodičem popisky je centrální panel – proto this na prvním řádku. QLabel *label1 = new QLabel( "Several Typical GUI Widgets", this ); label1->setPaletteForegroundColor( QColor( 128, 0, 0 ) ); label1->setFont( QFont( "Helvetica", 10, QFont::Normal ) ); label1->setMinimumHeight( 24 );
Qt: stručný průvodce – konstrukce centrálního panelu QHBoxLayout *imageRow = new QHBoxLayout( this ); QLabel *label2 = new QLabel( "", this ); QPixmap *pixmap = new QPixmap( "rcln.bmp" ); if ( pixmap ) label2->setPixmap( *pixmap ); listBox = new QListBox( this ); listBox->setMaximumWidth( 220 ); listBox->setFixedHeight( pixmap->height() ); listBox->insertItem( "Item 0" ); listBox->insertItem( QPixmap( zoomin_xpm ) ); … imageRow->addWidget( label2, 0, Qt::AlignLeft ); imageRow->addWidget( listBox, 0, Qt::AlignRight ); Obrázek vlevo je vytvořen jako popiska (QLabel), k níž je ovšem místo textu připojen obrázek (QPixmap). Povšimněte si, že i v „listboxu“ mohou být obrázky. Zoomin_xpm je pole znaků, v němž je obrázek definován (definici naleznete v souboru zoomin.xpm).
Qt: stručný průvodce – konstrukce centrálního panelu Zřízení textového editoru i nadpisu nad textovým polem mnoho komentářů nepotřebuje. Povšimňete si, že rolovací lišta se objevuje zcela automaticky. Objevování lišt lze modifikovat pomocí metody hScrollBarMode() , vScrollBarMode() (předvolené je automatické objevování se podle potřeby). Text lze získat metodou text jako QString. QLabel *label3 = new QLabel( "Write something here:", this ); label3->setAlignment( Qt::AlignLeft ); textEdit = new QTextEdit( this ); textEdit->setFixedHeight( 60 ); textEdit->setText( "Text edit area:\nrow2\nrow3\nanother row\nanother row\nrow" );
Qt: stručný průvodce – konstrukce centrálního panelu Pro zřizování skupin prvků je v Qt k dispozici třída QHGroupBox a QVGroupBox. Zde jsme použili první z nich. Napojení „check boxů“ na akce ukážeme později. QHGroupBox *checkGroup = new QHGroupBox( "Group", this ); check1 = new QCheckBox( "Check 1", checkGroup ); check2 = new QCheckBox( "Check 2", checkGroup );
Qt: stručný průvodce – konstrukce centrálního panelu Tlačítko s obrázkem a textem: Definici pole delete_xpm naleznete v souboru delete.xpm. Metoda addStrech vkládá pružnou mezeru. Napojení tlačítek na akce ukážeme později. QHBoxLayout *buttonRow = new QHBoxLayout( this ); QPushButton *button1 = new QPushButton( QPixmap( delete_xpm ), "", this ); button1->setFixedWidth( 24 ); button1->setFixedHeight( 24 ); QPushButton *button2 = new QPushButton( "Button", this ); button2->setFixedWidth( 96 ); button2->setFixedHeight( 24 ); buttonRow->addWidget( button1 ); buttonRow->addStretch(); buttonRow->addWidget( button2 );
Qt: stručný průvodce – napojení prvků GUI na akce V Qt generují prvky GUI signály. Signály mohou být zasílány metodám objektů, které programátor vytvoří. Propojení se zřizuje funkcí connect. Metoda má čtyři parametry: Objekt, který je zdrojem signálu, typ signálu, objekt a metoda, které signál zpracovávají. V našem případě signál vždy zpracovává objekt parent, což je rodič centrálního panelu, tedy hlavní okno. Tam proto musí být definovány všechny metody, které jsou uvedeny jako poslední parametr funkce connect. Propojení lze dynamicky měnit během chodu programu (k rozpojení slouží funkce disconnect mající tytéž parametry). connect( listBox, SIGNAL(selectionChanged()), parent, SLOT( onListBoxAction() ) ); connect( textEdit, SIGNAL(textChanged()), parent, SLOT( onTextChanged() ) ); connect( check1, SIGNAL(clicked()), parent, SLOT( onCheck1Action() ) ); connect( check2, SIGNAL(clicked()), parent, SLOT( onCheck2Action() ) ); connect( button1, SIGNAL(clicked()), parent, SLOT( onLeftButtonPressed() ) ); connect( button2, SIGNAL(clicked()), parent, SLOT( onRightButtonPressed() ) );
Qt: stručný průvodce – napojení prvků GUI na akce Ilustrace vytváření spojení (převzato od Trolltechu).
Qt: stručný průvodce – napojení prvků GUI na akce class MainWindow : public QMainWindow { Q_OBJECT public: CentralWidget *centralWidget; MainWindow(); private: int idMenuItem; public slots: void onOpen(); void onMeasuringLength(); void onListBoxAction(); void onTextChanged(); void onCheck1Action(); void onCheck2Action(); void onLeftButtonPressed(); void onRightButtonPressed(); void onOtherAction(); }; Povšimněte si, že metody zpracovávající signály jsou definovány jako tzv. „public slots“. Makro Q_OBJECT je požadováno kompilátorem meta objektů, který řeší mimo jiné napojení signálů na sloty. Musí být ve všech třídách obsahujících deklaraci signals nebo slots. Poznámka: Signály jsou generovány prvky GUI. Programátor může ale generovat také své vlastní signály. Deklarace signálu se podobá deklaraci metody. Je ale uvedena v sekci signals. Ke generování signálu se používá emit.
Qt: stručný průvodce – napojení prvků GUI na akce Často je zapotřebí jednotlivé prvky GUI povolovat, zakazovat nebo nastavovat. Následuje několik příkladů fileMenu->setItemEnabled( idMenuItem, false ); button1->setEnabled( true ); button1->setEnabled( false ); listBox->setSelected( 1, true ); check1->setChecked( true ); check2->setChecked( false ); textEdit->setFocus();
Qt: stručný průvodce - Co dál? … Podle potřeby používejte manuálu Qt (Qt Assistant nebo html dokumentaci) Můžete si přečíst text Qt 3.3 Whitepaper Navštivte www.trolltech.com