Qt中類裏爲什麼要加上Q_OBJECT這個東西呢,原來這是一個Qt定義的宏.它的作用是什麼呢?
原來這個宏中包含了Qt中最重要的一個機制:也就是信號和槽的機制.所有的Qt程序一定會使用這個機制!
下面我們可以先看一個簡單的小程序,一個類似於圖片加載器的小程序.
以下是先用Qt設計師簡單拖拽出來的一個沒有經過佈局的圖片:
我拖拽了一個QLabel框,兩個QPushButton,並且給他們改過了對象名.
以下是picture.cpp中的代碼:我會一行一行的解釋.
#include "picture.h"picture::picture(QWidget *parent) : QWidget(parent) { ui.setupUi(this); initSeaList(); initCliffList(); ui.label->setScaledContents(true); this->setWindowTitle(QString::fromLocal8Bit("圖片遊覽")); connect(ui.seaButton, SIGNAL(clicked()), this, SLOT(showSeaPictureSlot())); connect(ui.cliffButton, SIGNAL(clicked()), this, SLOT(showCliffPictureSlot())); } picture::~picture() { }void picture::showSeaPictureSlot() { ui.label->setPixmap(QPixmap(seaList[seaNumber % 10])); seaNumber++; }void picture::initSeaList() { for (int i = 0; i < 10; ++i) { QString path = "Pixmap/sea/" + QString::number(i) + ".jpg"; seaList.push_back(path); } }void picture::showCliffPictureSlot() { ui.label->setPixmap(QPixmap(cliffList[cliffNumber % 10])); cliffNumber++; }void picture::initCliffList() { for (int i = 0; i < 10; ++i) { QString path = "Pixmap/cliff/" + QString::number(i) + ".jpg"; cliffList.push_back(path); } }123456789101112131415161718192021222324252627282930313233343536373839404142434445
第1行:包含了”picture.h”文件,不用多解釋吧.
第6行:picure的構造函數中,ui.setupUi(this);用來調用Qt設計師中通過拖拽而形成的頁面.
第7.8行:對於兩個StringList的初始化,也就是把圖片的相對路徑放到容器中,方便以後調用.
第9行:ui.label->setScaledContents(true);這個成員函數的作用是把label框中的東西進行填充,舉個例子,如果裏面放了張圖片,但是圖片的大小比label框要小,那麼label框中就會有一些多餘的空白,顯得很難看,而調用了這個函數之後,就可以讓圖片填充滿這個label框.
第10行:this->setWindowTitle(QString::fromLocal8Bit(“圖片遊覽”));首先通過this指針來設置當前的標題爲”圖片遊覽”,但是由於Qt的編碼問題,顯示中文的話就會亂碼,所以有了fromLocal8Bit()這個函數,它是靜態的,所以可以直接用QString這個類名來調用它.
第11.12行:通過調用QObject::connect().這個連接函數,來吧QPushButton和Label連接起來,QPushButton如果被單擊了,就會發出clicked()信號,所以會調用一個我們自定義的showSeaPictureSlot函數,這就體現了信號與槽的機制.等於把兩個部件連接了起來,搭上了一層關係.
initSeaList函數中:首先我把10張圖片放在了文件夾裏,然後放在了Pixmap文件中這裏是我對於10張圖片的命名.
然後把Pixmap文件放在了這裏:
特別注意,要想在程序中調用外部圖片或者電影資源的話,最好和qrc文件放在一起.這樣可以便於查找路徑.(小編用的VS2013+Qt5.2版本,如果不會搭建這個環境的話,可以看我第一個帖子.)
initSeaList()函數中:QString類似於STL中的string,可以直接進行字符串相加,而資源文件的路徑是從qrc文件開始的.所以QString path = “Pixmap/sea/” + QString::number(i) + “.jpg”;,QString::number()也是QString的一個靜態函數,可以把數字轉化爲字符串,十分的方便.
然後調用seaList.push_back(path);把圖片的路徑放進去就行了.
showCliffPictureSlot()函數中:label->setPixmap(QPixmap())),這個函數是在label框中設置一個圖片的,並且QStringList類似於STL中的vector.所以它也是重載了[]的,可以直接調用.用cliffNumber保存上一次的序號,可以方便遊覽下一張,而cliffNumber%10的作用是:避免訪問的序號超過容器的大小.類似於以前的循環隊列的做法.
以下是picture.h的代碼:
#ifndef PICTURE_H#define PICTURE_H#include <QtWidgets/QWidget>#include "ui_picture.h"#include <QLabel>#include <QPushButton>#include <QPixmap>class picture : public QWidget{ Q_OBJECTprivate slots: void showSeaPictureSlot(); void showCliffPictureSlot();public: picture(QWidget *parent = 0); ~picture(); void initSeaList(); void initCliffList();private: Ui::pictureClass ui; int seaNumber = 0; int cliffNumber = 0; QStringList seaList; QStringList cliffList; };#endif // PICTURE_H1234567891011121314151617181920212223242526272829303132
這裏是運行編譯後的展示.
總結:
Q_OBJECT宏有着連接信號與宏的功能,一旦類中沒有這個宏定義的話,信號與槽的關聯也就消失了,有興趣的小夥伴們可以做個測試,你把這個宏給註釋掉,你就會發現程序一樣可以正常編譯通過,且成功運行,但是我點擊按鈕後,圖片是不會顯示的,原因就是缺少這個宏!