2.QT-窗口組件(QWidget),QT坐標系統,初探消息處理(信號與槽)


本章主要內容如下:

  • 1) 窗口組件(QWidget)
  • 2) QT坐標系統
  • 3) 消息處理(信號與槽)

 


 

窗口組件(QWidget)

介紹

  • Qt以組件對象的方式構建圖形用戶界面
  • Qt中沒有父組件的頂級組件,則被叫做窗口
  • 組件的類型分為:
  • 容器類(父組件)  :  用於包含功能的界面組件
  • 功能類(子組件)  :  用於實現特定的交互功能

如下圖所示:

 

比如上面的QgroupBox ,即屬於頂級組件的功能類(子組件),又是3個功能類組件的父組件(容器)

 

組件繼承

Qt中所有窗口組件繼承於QWidget類,而QWidget類繼承於QObject類QPaintDevice類.

 

如下圖所示(只舉例了3個窗口組件類):

 

 

QWidget組件介紹

  • QWidget能夠繪制自己(因為繼承了QPaintDevice類),也能夠處理用戶的輸入,比如點擊按鈕
  • QWidget是Qt窗口組件類的父類
  • Qt中每個窗口組件都可以當做一個QWidget (因為子類可以初始化父類)
  • QWidget類對象常作為父組件頂級組件使用

 

初探QWidget

1)新建工程,選擇Qt Gui應用,設置類信息:

 

 

2)生成QWidget模板

運行模板:

 

可以看到生成了一個窗口,然后我們來看看模板代碼,是如何生成的.

 

3)模板代碼如下所示

#include <QtGui/QApplication>

#include "widget.h"

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    QWidget w;                 //創建QWidget類對象

    w.show();                  //顯示QWidget類對象

   

    return a.exec();

}

根據之前講的內容可以發現,由於上面的QWidget w對象沒有父組件,所以QWidget w便成為了沒有父組件的頂級組件,從而生成了窗口.

 

Qt坐標系統

介紹

  • Qt使用統一的坐標系統定位窗口部件的位置和大小
  • QWidget類為組件類提供了窗口部件所需的坐標系統成員函數

在Qt里,坐標類型分為

  • 頂級窗口部件的定位
  • 窗口內部件的定位
  • 窗口部件的大小設置

坐標位置示意圖,如下所示

 

  

QWidget類提供的常用坐標系統成員函數有:

  • resize() :   設置窗口內部的寬高( width()和height()值)
  • move() :   設置整個窗口的x,y坐標( x()和y()值)
  • setGeometry() :  設置窗口內部的x,y,w,h(不包括標題和窗口邊框)
  • size()  :  獲取窗口部件的大小
  • pos() :   獲取窗口部件的位置
  • x()  :      獲取整個窗口x坐標
  • y()  :      獲取整個窗口y坐標
  • width()  :   獲取窗口內部的寬度(不包括外邊框的寬度)
  • height()  :   獲取窗口內部的高度(不包括窗口標題欄的高度)
  • const QRect&  geometry ()  :   獲取窗口內部的x,y,w,h(不包括標題和窗口邊框)
  • const QRect&  framgeometry ()  :   獲取整個窗口的x,y,w,h

可以參考下圖所示

 

注意: 在代碼里,執行show()后, 再獲取 x,y,w,h坐標 才有效

 

接下來我們通過3組不同的獲取坐標函數,來打印(x,y,w,h)坐標信息

代碼如下所示:

#include <QtGui>
#include "widget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    QPushButton b("button",&w);   //生成 QPushButton對象, 其父組件為 QWidget
/*設置窗口大小位置*/ w.resize(200,300); w.move(300,300);
/*設置按鈕大小位置*/ b.resize(100,50); b.move(50,100); w.show();
qDebug()
<<"QWidget:"; qDebug()<<"x()="<<w.x(); qDebug()<<"y()="<<w.y(); qDebug()<<"width()="<<w.width(); qDebug()<<"height()="<<w.height(); qDebug()<<"QWidget::geometry()"; qDebug()<<"x="<<w.geometry().x(); qDebug()<<"y="<<w.geometry().y(); qDebug()<<"w="<<w.geometry().width(); qDebug()<<"h="<<w.geometry().height(); qDebug()<<"QWidget::frameGeometry()"; qDebug()<<"x="<<w.frameGeometry().x(); qDebug()<<"y="<<w.frameGeometry().y(); qDebug()<<"w="<<w.frameGeometry().width(); qDebug()<<"h="<<w.frameGeometry().height(); return a.exec(); }

運行打印:

QWidget:
x()= 300
y()= 300
width()= 200
height()= 300

QWidget::geometry()
x= 308
y= 330
w= 200
h
= 300 QWidget::frameGeometry() x= 300 y= 300 w= 216 h= 338

 可以看到,獲取的窗內坐標(x,y)永遠比窗外坐標大,窗外大小(w,h)永遠比窗內大小大

 

初探消息處理(信號與槽)

QT封裝了具體操作系統的消息機制,如下圖所示:

 

 

 

Qt中定義了與系統信息相關的概念

信號(signal)

  • 由操作系統產生的消息,比如按鍵消息

槽(slot)

  • 程序中的消息處理函數,用來處理信號,比如處理按鍵點擊信號

連接(Connect)

  • 將系統信息綁定到信息處理函數(信號到槽的連接),通過connect()函數實現,且必須發生在兩個Qt類對象之間,如下圖所示:

                                     

 

connect()函數原型

bool QObject::connect (
        const QObject * sender,                 //發送對象
        const char * signal,                     //消息名(信息)
        const QObject * receiver,                //接收對象
        const char * method,                     //接收對象的成員函數(槽)
        Qt::ConnectionType type = Qt::AutoConnection ) ;   //正常情況不需要設置 //當出現sender對象的signal信號,則會自動調用receiver對象的method
//連接成功,則返回true;否則返回false。

 

在信號與槽里,Qt引進了幾個新的關鍵字:

  • SIGNAL :指定消息名(信號),用於connect()函數里
  • SLOT   : 指定消息處理函數名(槽),用於connect()函數里
  • Q_OBJECT : 指定該類擁有槽(消息處理),在類聲明的內部開始處加上Q_OBJECT即可
  • slots  : 用於在類中聲明消息處理函數,比如:
private slots:
         void buttonCliked();

 

初探信號與槽

通過點擊按鈕,使程序自動退出,代碼如下所示:

#include <QtGui>
#include <QApplication>
#include <QPushButton>

int main(int argc,char * argv[])
{
  QApplication app(argc,argv);
  QPushButton *quitButton = new QPushButton("Quit");

  QObject::connect(quitButton, SIGNAL(clicked()), &app, SLOT(quit()));
  //*quitButton(發送對象), &app(接收對象)
  //quit()作用是退出程序, QApplication的成員函數
  //clicked()作用是鼠標點擊, 很多常用組件的成員函數

    quitButton->show();
    return app.exec();
}

其中上面的quit() 和clicked()都是系統預定義好的,接下來我們自定義槽

首先需要注意

    • 類中聲明槽(處理信號的成員函數)時,需要slots聲明
    • 槽和信號的函數參數必須一致,比如clicked()和quit()都是無參數的
    • SIGNAL和SLOT指定的函數(信號和槽)只能包含參數類型,不能包含參數名

 

開始試驗,通過不同按鈕點擊,來打印不同的信息

寫QButtonDebug.h:

#ifndef QBUTTONDEBUG_H
#define QBUTTONDEBUG_H

#include
<QWidget> #include <QPushButton> class QButtonDebug : public QWidget { Q_OBJECT //指定該類擁有slots(槽) private: QPushButton *mbton1; QPushButton *mbton2; private slots: //通過slots 聲明 槽 void buttonCliked(); public: explicit QButtonDebug(QWidget *parent=0,Qt::WindowFlags f=0); }; #endif

 

寫QButtonDebug.cpp:

#include "QButtonDebug.h"
#include <QDebug>
QButtonDebug:: QButtonDebug(QWidget *parent,Qt::WindowFlags f) : QWidget(parent,f) //顯示初始化父類 { mbton1 = new QPushButton("button1",this); mbton2 = new QPushButton("button2",this); /*設置按鈕坐標*/ mbton1->resize(100,50); mbton1->move(50,50); mbton2->resize(100,50); mbton2->move(50,100); /*設置連接*/ QObject::connect(mbton1,SIGNAL(clicked()),this,SLOT(buttonCliked())); QObject::connect(mbton2,SIGNAL(clicked()),this,SLOT(buttonCliked())); QWidget::show(); }
void QButtonDebug:: buttonCliked()           //消息處理函數 { QPushButton* p_buton =dynamic_cast<QPushButton*>(sender()); //獲取發送信號的對象 使用 qDebug()<< p_buton->text(); //更據不同的按鈕 打印不同信息 }

 

寫main.cpp

#include <QtGui>
#include <QApplication>
#include "QButtonDebug.h"

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

  QButtonDebug b(NULL,Qt::WindowCloseButtonHint);      
                     // Qt::WindowCloseButtonHint:去掉標題按鈕提示

  return a.exec();
}

 

運行測試

如下圖所示,可以看到通過點擊不同的按鈕,便能打印不同的信息出來

 

 

深入信號槽-自定義信號

介紹

  • 只有Qt類才能定義信號,且該類必須在頭文件中聲明
  • 信號函數只能通過signals關鍵字進行聲明,不能定義,且返回值必須是void類型
  • 信號函數的屬性會被自動設置為protected類型
  • 發送信號時,只需要通過emit關鍵字調用信號函數即可
  • 如果信號函數的參數多於槽函數時,多於的參數將被忽略
  • 槽函數的返回值必須是void類型,且可以被其它普通成員函數調用


自定義信號示例:

class MySignal : public QObject
{
  Q_OBJECT
signals:     //自定義信號函數
  void SendSignal(int i); 

public:
  void send(int i)
  {
    emit SendSignal(i); //調用信號函數,發送信號
  } 
};

自定義槽函數示例:

class MySlot : public QObject
{
  Q_OBJECT
protected slots:   void RecvSlot(int i)   {     qDebug()<<"Send:"<<sender()->objectName(); //打印發送對象名     qDebug()<<"Recv:"<<i;     qDebug()<<endl;   } };

 


信號與槽的組合

  • 信號函數可以連接多個槽函數
  • 多個信號函數可以連接一個槽函數
  • 一個信號就可以連接到另一個信號
  • 通過connect函數進行連接,也可以通過disconnect函數取消連接

示例1-多個信號連接一個槽:

    MySignal s1;
    MySignal s2;
    MySlot t;

    s1.setObjectName("Signal1");
    s2.setObjectName("Signal2"); 
    QObject::connect(&s1,SIGNAL(SendSignal(int)),&t,SLOT(RecvSlot(int)));     QObject::connect(&s2,SIGNAL(SendSignal(int)),&t,SLOT(RecvSlot(int)));     s1.send(10);     s2.send(12);

打印:

Send: "Signal1" 
Recv: 10

Send: "Signal2" 
Recv: 12

 

示例2-信號1連接信號2,信號2連接槽:

    MySignal s1;
    MySignal s2;
    MySlot t;
    s1.setObjectName("Signal1");
    s2.setObjectName("Signal2");
    QObject::connect(&s1,SIGNAL(SendSignal(int)),&s2,SIGNAL(SendSignal(int)));
    QObject::connect(&s2,SIGNAL(SendSignal(int)),&t,SLOT(RecvSlot(int)));
    s1.send(10);
    s2.send(12);

打印:

    Send: "Signal2" 
    Recv: 10 
    Send:
"Signal2"     Recv: 12

 

 

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM