Qt logo


Kapitola 5: Stavebné bloky


Screenshot of tutoriálu č. five

Tento príklad ukazuje ako vytvoriť a pospájať dohromady niekoľko widgetov použijúc signály a sloty, a ako spracovať udalosť zmeny veľkosti.

/****************************************************************
**
** Qt tutorial 5
**
****************************************************************/

#include <qapplication.h>
#include <qpushbutton.h>
#include <qscrollbar.h>
#include <qlcdnumber.h>
#include <qfont.h>

class MyWidget : public QWidget
{
public:
    MyWidget( QWidget *parent=0, const char *name=0 );
protected:
    void resizeEvent( QResizeEvent * );
private:
    QPushButton *quit;
    QScrollBar  *sBar;
    QLCDNumber  *lcd;
};

MyWidget::MyWidget( QWidget *parent, const char *name )
        : QWidget( parent, name )
{
    setMinimumSize( 200, 200 );

    quit = new QPushButton( "Quit", this, "quit" );
    quit->setGeometry( 10, 10, 75, 30 );
    quit->setFont( QFont( "Times", 18, QFont::Bold ) );

    connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );

    lcd  = new QLCDNumber( 2, this, "lcd" );
    lcd->move( 10, quit->y() + quit->height() + 10 );

    sBar = new QScrollBar( 0, 99,                       // range
                           1, 10,                       // line/page steps
                           0,                           // inital value
                           QScrollBar::Horizontal,      // orientation
                           this, "scrollbar" );

    connect( sBar, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)) );
}

void MyWidget::resizeEvent( QResizeEvent * )
{
    sBar->setGeometry( 10, height() - 10 - 16, width() - 20, 16 );
    lcd->resize( sBar->width(), sBar->y() - lcd->y() - 5 );
}

int main( int argc, char **argv )
{
    QApplication a( argc, argv );

    MyWidget w;
    w.setGeometry( 100, 100, 200, 200 );
    a.setMainWidget( &w );
    w.show();
    return a.exec();
}

Prechádzka riadok po riadku

    #include <qapplication.h>
    #include <qpushbutton.h>
    #include <qscrollbar.h>
    #include <qlcdnumber.h>
    #include <qfont.h>

Máme tu dva nové súbory, qscrollbar.h a qlcdnumber.h, pretože používame dve nové triedy - QScrollBar a QLCDNumber.

    class MyWidget : public QWidget
    {
    public:
        MyWidget( QWidget *parent=0, const char *name=0 );

Nič nové v porovnaní s predchádzajúcou kapitolou.

    protected:
        void resizeEvent( QResizeEvent * );

MyWidget teraz získal schopnosť spracovať udalosť zmeny veľkosti.

resizeEvent() je jedna z mnohých virtuálnych funkcií triedy QWidget, ktoré sa používajú na odovzdávanie udalostí rôznych druhov widgetom. Tieto funkcie obsluhy udalostí sú jedným z centrálnych mechanizmov riadenia toku programu v Qt, tým druhým je mechanizmus signálov a slotov.

Táto funkcia je volaná, ako sa dalo čakať, vždy, keď užívateľ alebo niektorá časť programu zmení veľkosť widgetu.

    private:
        QPushButton *quit;
        QScrollBar  *sBar;
        QLCDNumber  *lcd;
    };

V kapitole tri si MyWidget nepamätal svoje dcérske widgety. Teraz si ich už pamätá, a teda môže meniť ich veľkosť.

    MyWidget::MyWidget( QWidget *parent, const char *name )
            : QWidget( parent, name )
    {
        setMinimumSize( 200, 200 );

Pretože chceme, aby MyWidget pracoval so všetkými veľkosťami nad 200 x 200 pixelov, nastavíme iba minimálnu veľkosť.

        lcd  = new QLCDNumber( 2, this, "lcd" );
        lcd->move( 10, quit->y() + quit->height() + 10 );

lcd je QLCDNumber, widget, ktorý zobrazuje čísla ako na LCD displayi. Táto inštancia je nastavená na zobrazovanie dvoch číslic, aby bola dcérskym widgetom objektu this a jej meno je "lcd".

Je umiestnená na pozícii x = 10 a y s medzerou 10 pixelov medzi tlačidlom quit a LCD číslom. Mimochodom, nemusel by byť zlý nápad pozrieť sa na popis súradnicového systému. Všimnite si, že tu nenastavujeme veľkosť LCD widgetu, resizeEvent() to urobí za nás, keď bude nastavená veľkosť MyWidget-u.

Miesta s množstvom prácneho kódovania ako toto sú únavné, keď máte veľa widgetov, ale Qt bohužiaľ zatiaľ neobsahuje dobrý vizuálny vývojový prostriedok. Ale kto si počká, ten sa dočká.

        sBar = new QScrollBar( 0, 99,                       // rozsah
                               1, 10,                       // krok v riadkoch/stránkach
                               0,                           // počiatočná hodnota
                               QScrollBar::Horizontal,      // orientácia
                               this, "scrollbar" );

QScrollBar je klasická systémová rolovacia lišta. Táto má niekoľko možných konštruktorov, obsahuje aj konštruktory s menej argumentami, ale potom by sme na dosiahnutie požadovaného stavu museli použiť niekoľko volaní funkcií.

Nenastavujeme geometriu rolovacej lišty, udalosť zmeny veľkosti ju nastaví sama.

        connect( sBar, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)) );

Tu používame mechanizmus signálov a slotov na spojenie signálu valueChanged() (hodnota zmenená) rolovacej lišty so slotom display() (zobraz) LCD čísla.

Kedykoľvek sa zmení hodnota rolovacej lišty (posunie sa), vyšle signál valueChanged(). Pretože sme tento signál pripojili na slot display() LCD čísla, slot je zavolaný vždy, keď je vyslaný signál. Ani jeden z objektov nevie nič o tom druhom. Toto je esencia programovania komponent.

Sloty sú inak normálne C++ funkcie a platia pre ne normálne C++ prístupové práva.

    void MyWidget::resizeEvent( QResizeEvent * )
    {
        sBar->setGeometry( 10, height() - 10 - 16, width() - 20, 16 );
        lcd->resize( sBar->width(), sBar->y() - lcd->y() - 5 );
    }

Tu chceme pri zmene veľkosti widgetu pekne nastaviť veľkosť jeho dcérskych widgetov. Chceme, aby LCD číslo bolo nad rolovacou lištou. Najprv teda umiestnime lištu na spodný okraj MyWidget-u.

Geometria rolovacej lišty je nastavená tak, aby vznikol 10 pixelový okraj medzi ľavým, dolným a pravým okrajom MyWidget-u a lišty, a jej výška je nastavená na 16 pixelov, čo je odporúčaná hodnota pre väčšinu štýlov zobrazenia.

Pamätajte, že poradie argumentov setGeometry() je ľavý, horný, šírka, výška.

X-ová pozícia je jasná - 10 pixelov od ľavého okraja. Y-ová je počítaná z celkovej veľkosti widgetu, od ktorej odpočítame 10 pixelov od dolného okraja a 16 pixelov výšky rolovacej lišty. Šírka lišty by mala byť celková šírka widgetu mínus 10 pixelov z každej strany. Ako sme spomenuli vyššie, výšku nastavíme na 16 pixelov.

Nakoniec nastavíme veľkosť LCD čísla. Šírka je ľahká, nastavíme ju na rovnakú hodnotu ako šírka rolovacej lišty. Výška je medzi horným okrajom lišty a horným okrajom LCD čísla mínus 5 pixelov na okraj. Spomeňte si z konštruktora, že sme LCD číslo umiestnili pod tlačidlo quit.

Automatické umiestňovanie widgetov tak ako tu je únavné. Qt obsahuje triedy na správu geometrie, ktoré túto prácu zjednodušujú. Tito triedy sú QBoxLayout a QGridLayout. Ďalšie verzie tohto tutoriálu budú obsahovať kapitoly o správe geometrie. Buďte trpezliví!

Správanie

LCD číslo reaguje na všetko, čo urobíte s rolovacou lištou a widgety skutočne dobre pracujú so zmenou veľkosti.

Cvičenia

Skúste zmeniť LCD číslo pridaním viac číslic, alebo zmenou módu. Môžete dokonca skúsiť pridať tlačidlá na zmenu módu.

Zmeňte rozsah rolovacej lišty.

Skúste upraviť aplikáciu tak, aby skončila v prípade, že LCD číslo pretečie (že sa pokúsi zobraziť číslo s väčším počtom číslic, než má).

Teraz môžete ísť na kapitolu šesť.

[Predchádzajúci tutoriál] [Ďalší tutoriál] [Hlavná stránka tutoriálu]


Copyright © 1998 Troll TechTrademarks
Qt version 1.42