QT Widget

  • QLineEdit:單行文字輸入的 widget。
    1. 建構函式和常用成員函式:
      #include <qlineedit.h>
      QLineEdit::QlineEdit (QWidget *parent, const char* name = 0 )
      QLineEdit::QLineEdit (const QString &contents, QWidget *parent,
                             const char *name = 0 )
      QLineEdit::QLineEdit (const QString &contents,
                             const QString &inputMask,
                             QWidget *parent, const char *name = 0 )
      void    setInputMask (const QString &inputMask)
      void    insert (const QString &newText )
      bool    isModified (void)
      void    setMaxLength (int length)
      void    setReadOnly (bool read)
      void    setText (const QString &text)
      QString text (void)
      void    setEchoMode(EchoMode mode)
      
    2. 屬性 EchoMode 決定文字如何顯示在 widget 上。它可以有以下三種數值:
      1. QLineEdit::Normal:顯示輸入字元(預設值)。
      2. QLineEdit::Password:顯示星號,取代真正的字元。
      3. QLineEdit::NoEcho:不顯示任何東西。
    3. 使用 setEchoMode 設定 EchoMode 模式:
      lineEdit->setEchoMode(QLineEdit::Password);
      
    4. inputMask 是字元構成的字串,用來說明接受的字元,其與正規表示式使用相同的原則。
      1. inputMask 字元代表能不能存在某字元。
        意義 必要性字元 選擇性字元
        ASCII A-Z,a-z A a
        ASCII A-Z,a-z,0-9 N n
        任何字元 X x
        數值 0-9 9 0
        數值 1-9 D d
      2. inputMask 結尾可以選擇性加上分號。
      3. inputMask 進階的特殊字元:
        # 數字或 +, - 符號之選擇性字元。
        > 將隨後的字元變成大寫。
        < 將隨後的字元變成小寫。
        ! 停止轉換。
        \ 跳脫字元
    5. 遮罩範例:
      1. “AAAAAA-999D”
        1. 可接受 Athens-2004,
        2. 但不能接受 Sydney-2000 或 Atlanta-1996。
      2. “AAAAnn-99-99;”
        1. 可接受 March-03-12,
        2. 但不能接受 May-03-12 或 September-03-12。
      3. “000.000.000.000”:允許 IP 位址,例如 192.168.0.1。

  • 實例:QLineEdit
    1. 標頭檔案 LineEdit.h。
      #include <qmainwindow.h>
      #include <qlineedit.h>
      #include <qstring.h>
      class LineEdit : public QMainWindow
      {
        Q_OBJECT
        public:
          LineEdit(QWidget *parent = 0, const char *name = 0);
          QLineEdit *password_entry;
        private slots:
          void Clicked();
      };
      
    2. 程式檔案 LineEdit.cpp。
      #include "LineEdit.moc"
      #include <qpushbutton.h>
      #include <qapplication.h>
      #include <qlabel.h>
      #include <qlayout.h>
      #include <iostream>
      LineEntry::LineEntry(QWidget *parent, const char *name) :
      QMainWindow(parent, name)
      {
        QWidget *widget = new QWidget(this);
        setCentralWidget(widget);
      
      # 使用 QGridLayout 來安排 widget。指定行數、列數、邊界設定和間隔。
        QGridLayout *grid = new QGridLayout(widget,3,2,10, 10,"grid");
        QLineEdit *username_entry = new QLineEdit( widget,
                                             "username_entry");
        password_entry = new QLineEdit( widget, "password_entry");
        password_entry->setEchoMode(QLineEdit::Password);
      
      # 在方格中加入一個 widget,必須告知行編號、列編號,而起始值為(0,0)代表左上方的格子。
        grid->addWidget(new QLabel("Username", widget, "userlabel"),
                       0, 0, 0);
        grid->addWidget(new QLabel("Password", widget, "passwordlabel"),
                       1, 0, 0);
        grid->addWidget(username_entry, 0,1, 0);
        grid->addWidget(password_entry, 1,1, 0);
        QPushButton *button = new QPushButton ("Ok", widget, "button");
        grid->addWidget(button, 2,1,Qt::AlignRight);
        resize( 350, 200 );
        connect (button, SIGNAL(clicked()), this, SLOT(Clicked()));
      }
      void LineEntry::Clicked(void)
      {
        std::cout << password_entry->text() << "\n";
      }
      int main(int argc, char **argv)
      {
        QApplication app(argc,argv);
        LineEntry *window = new LineEntry();
        app.setMainWidget(window);
        window->show();
        return app.exec();
      }
      
    3. 程式執行結果:
      [dywang@dywOffice chapter17]$ moc LineEdit.h -o LineEdit.moc
      [dywang@dywOffice chapter17]$ g++ -o lineedit LineEdit.cpp \
      -I$QTDIR/include -L$QTDIR/lib -lqt-mt
      [dywang@dywOffice chapter17]$ ./lineedit
      
      Image lineedit
    4. 結果說明:
      1. 產生兩個 QLineEdit widget,其中一個設定 EchoMode 讓它變成密碼輸入的視窗;
      2. 按下按鈕時就會印出結果。

  • Qt 按鈕(Buttons)
    1. QButton 的成員函式:
      #include <qbutton.h>
      virtual void QButton::setText ( const QString & )
      virtual void QButton::setPixmap ( const QPixmap & )
      bool QButton::isToggleButton () const
      virtual void QButton::setDown ( bool )
      bool QButton::isDown () const
      bool QButton::isOn () const
      enum QButton::ToggleState { Off, NoChange, On }
      ToggleState QButton::state () const
      
    2. 函式說明:
      1. isToggleButton 函式表示按鈕是否為雙態(toggle)的按鈕(亦即有 on 或 off 狀態),預設為 FALSE。
      2. isDown 函式表示按鈕被按下就回覆 TRUE。
      3. 如果按鈕拴牢( toggled ), isOn 函式回傳 TRUE。
    3. QButton 三個子類別:PushButton、CheckBox 和 RadioButton。
      Image button_pcr

  • QPushButton:簡單的按鈕 widget,被按下時就會執行一些動作。
    1. 建構函式和有用的成員函式:
      #include <qpushbutton.h>
      QPushButton (QWidget *parent, const char *name = 0)
      QPushButton (const QString &text, QWidget *parent,
                 const char *name = 0)
      QPushButton (const QIconSet &icon, const QString &text,
                   QWidget *parent, const char * name = 0 )
      void QPushButton::setToggleButton (bool);
      
    2. 按鈕上可以有文字或圖示。例如 OK 或 Cancle。
    3. 可呼叫 setToggleButton,從無狀態(stateless)按鈕變成雙態(toggle)按鈕。

  • QCheckBox
    1. 建構函式和有用的成員函式:
      #include <qcheckbox.h>
      QCheckBox (QWidget *parent, const char *name = 0 )
      QCheckBox (const QString &text, QWidget *parent,
                 const char *name = 0 )
      bool QCheckBox::isChecked ()
      void QCheckBox::setTristate ( bool y = TRUE )
      bool QCheckBox::isTristate ()
      
    2. 一般只有 on 或 off 狀態資訊;
    3. 也可變成三種狀態,中間的狀態代表“沒有改變”。

  • QRadioButton
    1. 建構函式和一個成員函式:
      #include <qradiobutton.h>
      QRadioButton (QWidget *parent, const char *name = 0 )
      QRadioButton (const QString &text, QWidget *parent,
                       const char *name = 0 )
      bool   QRadioButton::isChecked ()
      
      Image button_pcr1
    2. 通常是成群的,在同一個時間只能按下群組中的一個按鈕。
    3. 還要透過 QButtonGroup 類別來控制群組和唯一選擇性。

  • QButtonGroup
    1. 建構函式和一個成員函式:
      #include <qbuttongroup.h>
      QButtonGroup (QWidget *parent = 0, const char * name = 0 )
      QButtonGroup (const QString & title, QWidget * parent = 0,
                       const char * name = 0 )
      int   insert (QButton *button, int id = -1)
      void  remove (QButton *button)
      int   id (QButton *button) const
      int   count () const
      int   selectedId () const
      
    2. 要將按鈕加入 QButtonGroup 可以使用 insert(),或指定 QButtonGroup 為要按鈕的父親 widget。
    3. 在 insert()中,還可以指定一個 id,以辨識每個按鈕。
    4. selectedId 會回傳被選擇按鈕的 id。
    5. 加入群組的 QRadioButton 都會自動設成排他性,不會有重複選擇的問題。

  • 實例:QButtons
    1. 檔案 Buttons.h:
      #include <qmainwindow.h>
      #include <qcheckbox.h>
      #include <qbutton.h>
      #include <qradiobutton.h>
      class Buttons : public QMainWindow
      {
        Q_OBJECT
        public:
          Buttons(QWidget *parent = 0, const char *name = 0);
      
      # 在 slot 函式中會查詢按鈕的狀態,所以在類別定義中宣告按鈕指標為私有的。
        private:
          void PrintActive(QButton *button);
          QCheckBox *checkbox;
          QRadioButton *radiobutton1, *radiobutton2;
        private slots:
          void Clicked();
      };
      
    2. 檔案 Buttons.cpp:
      #include "Buttons.moc"
      #include <qbuttongroup.h>
      #include <qpushbutton.h>
      #include <qapplication.h>
      #include <qlabel.h>
      #include <qlayout.h>
      #include <iostream>
      Buttons::Buttons(QWidget *parent, const char *name) :
      QMainWindow(parent, name)
      {
        QWidget *widget = new QWidget(this);
        setCentralWidget(widget);
        QVBoxLayout *vbox = new QVBoxLayout(widget,5, 10,"vbox");
        checkbox = new QCheckBox("CheckButton", widget, "check");
        vbox->addWidget(checkbox);
      
      # 為兩個 radio 按鈕,產生一個 QButtonGroup:
        QButtonGroup *buttongroup = new QButtonGroup(0);
        radiobutton1 = new QRadioButton("RadioButton1", widget, "radio1");
        buttongroup->insert(radiobutton1);
        vbox->addWidget(radiobutton1);
        radiobutton2 = new QRadioButton("RadioButton2", widget, "radio2");
        buttongroup->insert(radiobutton2);
        vbox->addWidget(radiobutton2);
        QPushButton *button = new QPushButton ("Ok", widget, "button");
        vbox->addWidget(button);
        resize( 350, 200 );
        connect (button, SIGNAL(clicked()), this, SLOT(Clicked()));
      }
      
    3. 印出按鈕狀態的成員函式:
      void Buttons::PrintActive(QButton *button)
      {
        if (button->isOn())
          std::cout << button->name() << " is checked\n";
        else
          std::cout << button->name() << " is not checked\n";
      }
      void Buttons::Clicked(void)
      {
         PrintActive(checkbox);
         PrintActive(radiobutton1);
         PrintActive(radiobutton2);
         std::cout << "\n";
      }
      int main(int argc, char **argv)
      {
        QApplication app(argc,argv);
        Buttons *window = new Buttons();
        app.setMainWidget(window);
        window->show();
        return app.exec();
      }
      
    4. 程式執行結果。
      [dywang@dywOffice chapter17]$ moc Buttons.h -o Buttons.moc
      [dywang@dywOffice chapter17]$ g++ -o buttons Buttons.cpp\
      >-I$QTDIR/include -L$QTDIR/lib -lqt-mt
      [dywang@dywOffice chapter17]$ ./buttons
      check is checked
      radio1 is checked
      radio2 is not checked
      
      Image buttons

  • QComboBox
    1. Radio 按鈕有六個以上的選項時,會讓視窗難以調整。
    2. 建構函式
      # QComboBox 建構函式中的布林參數 TRUE,指定 QComboBox 為可讀寫。
      QComboBox *combo = new QComboBox(TRUE, parent, “widgetname”);
      
      Image combobox0
    3. 加入選項,輸入型態可以為 QStrings 或使用傳統的 char *格式。
      combo->insertItem(QString(“An Item”), 1);
      # 數值 1 代表設定這個選項為串列中的第一個選項。
      # 如果要將加到串列尾端,只要傳入任何負的整數。
      
    4. 利用 char * 陣列加入多個選項:
      char* weather[] = {“Thunder”, “Lightning”, “Rain”, 0};
      combo->insertStrList(weather, 3);
      
    5. 呼叫 QComboBox 的 setInsertionPolicy()成員函式:
      combo->setInsertionPolicy(QComboBox::AtTop);
      
      關鍵字串 插入策略
      QComboBox::AtTop 將新項目插到串列的第一個選項。
      QComboBox::AtBottom 將新項目插到串列的最後一個選項。
      QComboBox::AtCurrent 取代先前選擇的選項。
      QComboBox::BeforeCurrent 將新項目插到先前選擇的選項之前。
      QComboBox::AfterCurrent 將新項目插到先前選擇的選項之後。
      QComboBox::NoInsertion 不要將新選項插入串列中。
    6. QComboBox 的建構函式和其他成員函式:
      #include <qcombobox.h>
      QComboBox (QWidget *parent = 0, const char *name = 0)
      QComboBox (bool readwrite, QWidget *parent = 0, const char *name = 0)
      # count 回覆串列選項的數量。
      int      count ()
      # QStringList 和 QStrList 是 Qt 字串集合類別,可以用來加入多個選項。
      void     insertStringList (const QStringList &list, int index = -1)
      void     insertStrList (const QStrList &list, int index = -1)
      void     insertStrList (const QStrList *list, int index = -1)
      void     insertStrList (const char **strings, int numStrings = -1,
                              int index = -1)
      # insertItem 加入選項;
      void     insertItem (const QString &t, int index = -1)
      # removeItem() 移除選項;
      void     removeItem (int index)
      # CurrrentItem() 取得目前選項;
      virtual void setCurrentItem (int index)
      # CurrrentText() 取得目前選項內容;
      QString currentText ()
      virtual void setCurrentText (const QString &)
      # setEditable() 切換可編輯的狀態。
      void     setEditable (bool)
      

  • 實例:設計兩個 QComboBox widget,一個可以編輯,另一個是唯讀。
    1. 程式檔案 ComboBox.cpp:
      #include "ComboBox.moc"
      #include <qlayout.h>
      #include <iostream>
      ComboBox::ComboBox(QWidget *parent, const char *name) :
      QMainWindow(parent, name)
      {
        QWidget *widget = new QWidget(this);
        setCentralWidget(widget);
        QVBoxLayout *vbox = new QVBoxLayout(widget, 5, 10,"vbox");
        QComboBox *editablecombo = new QComboBox(TRUE, widget, "editable");
        vbox->addWidget(editablecombo);
        QComboBox *readonlycombo = new QComboBox(FALSE, widget, "readonly");
        vbox->addWidget(readonlycombo);
        static const char* items[] = { "Macbeth",
                                   "Twelfth Night", "Othello", 0 };
        editablecombo->insertStrList (items);
        readonlycombo->insertStrList (items);
      # 當一個新選項被選擇之後,QComboBox 會發出 textChanged(QString &) 信號。
        connect (editablecombo, SIGNAL(textChanged(const QString&)),
                 this, SLOT(Changed(const QString&)));
        resize( 350, 200 );
      }
      
      # QString 參數 s,會被信號傳送。
      void ComboBox::Changed(const QString& s)
      {
        std::cout << s << "\n";
      }
      
      int main(int argc, char **argv)
      {
        QApplication app(argc,argv);
        ComboBox *window = new ComboBox();
        app.setMainWidget(window);
        window->show();
        return app.exec();
      }
      
    2. 執行:命令列看到新選擇的選項被印出來。
      [dywang@dywOffice chapter17]$ moc ComboBox.h -o ComboBox.moc
      [dywang@dywOffice chapter17]$ g++ -o combobox ComboBox.cpp \
      >-I$QTDIR/include -L$QTDIR/lib -lqt-mt
      [dywang@dywOffice chapter17]$ ./combobox
      Twelfth Night
      
      Image combobox

  • QListView
    1. QListView 能以目錄架構的方式顯示,按下加號和減號擴展或緊縮子元件,與檔案顯示程式一樣。
    2. 建構函式:只要指定父親和 widget 名稱。
      QListView *view = new QListView(parent, “name”);
      
    3. 設定欄位的標題,要利用 addColumn()成員函式:
      view->addColumn("Left Column", width1 ); // Fixed width
      view->addColumn("Right Column"); // Width autosizes
      

  • QListViewItem:將列元件傳入 QListView 中:
    1. 建構函式:
      QListViewItem::QListViewItem ( QListView * parent, QString label1, 
      QString label2 = QString::null, QString label3 = QString::null, 
      QString label4 = QString::null, QString label5 = QString::null, 
      QString label6 = QString::null, QString label7 = QString::null, 
      QString label8 = QString::null )
      # 可以提供八個行的標籤,若不需要可不給參數或指定 NULL
      
    2. 將列元件傳入 view :
      QListViewItem *toplevel = new QListViewItem(view, "Left Data",
                                                    "Right Data");
      
    3. 將列元件傳入 toplevel 子節點:
      new QListViewItem(toplevel, "Left Data", "Right Data");
                                               // A Child of toplevel
      
    4. QListViewItem 成員函式:
      #include <qlistview.h>
      virtual void    insertItem ( QListViewItem * newChild )
      virtual void    setText ( int column, const QString & text )
      virtual QString text ( int column ) const
      QListViewItem   *firstChild () const
      QListViewItem   *nextSibling () const
      QListViewItem   *parent () const
      QListViewItem   *itemAbove ()
      QListViewItem   *itemBelow ()
      
    5. 實例:印出上層節點的第一欄
      QListViewItem *child = view->firstChild();
      while(child)
      {
        cout << myChild->text(1) << "\n";
        myChild = myChild->nextSibling(); 
      }
      

  • 實例:QListView
    1. 跳過標頭檔案 ListView.h,直接看類別檔案 ListView.cpp:
      #include "ListView.moc"
      ListView::ListView(QWidget *parent, const char *name) :
      QMainWindow(parent, name)
      {
        listview = new QListView(this, "listview1");
        listview->addColumn("Artist");
        listview->addColumn("Title");
        listview->addColumn("Catalogue");
        listview->setRootIsDecorated(TRUE);
        QListViewItem *toplevel = new QListViewItem(listview,
                              "Avril Lavigne", "Let Go", "AVCD01");
        new QListViewItem(toplevel, "Complicated");
        new QListViewItem(toplevel, "Sk8er Boi");
        setCentralWidget(listview);
      }
      
      int main(int argc, char **argv)
      {
        QApplication app(argc,argv);
        ListView *window = new ListView();
        app.setMainWidget(window);
        window->show();
        return app.exec();
      }
      
    2. 編譯和執行 ListView
      [dywang@dywOffice chapter17]$ moc ListView.h -o ListView.moc
      [dywang@dywOffice chapter17]$ g++ -o listview ListView.cpp \
      -I$QTDIR/include -L$QTDIR/lib -lqt-mt
      [dywang@dywOffice chapter17]$ ./listview
      
      Image listview

  DYWANG_HOME