C++链式继承
??????? 繼承,對于學習C++的每一個人來說,都不會陌生。在Qt的開發中,如果你需要對一個無邊框的界面支持move操作,那么你就得通過繼承重寫虛函數來實現,這并不難,但如果我還需要對一個按鈕支持移動,一般情況,當然是Crtl + c 、Crtl + v搞定,但我們不難發現,對于move這個操作來說,其實代碼完全一模一樣,那么有沒有什么辦法可以簡化,可以一勞永逸呢?
??????? 答案是肯定的,這里我們就需要用到C++的模板來實現了,即本文要介紹的鏈式繼承。
??????? 前面有實現過move操作,這里將它抽取出來,代碼如下:
1: #include <QWidget>
2: #include <QMouseEvent>
3: #include <QPoint>
4:
5: //T 為基類,繼續擁有一個QWidget *parent參數的構造函數
6: template <typename T>
7: class WidgetMove : public T
8: {
9: public:
10: WidgetMove(QWidget *parent = 0):T(parent)
11: {
12: }
13: protected:
14: void mousePressEvent(QMouseEvent *event)
15: {
16: //當鼠標左鍵按下時,記錄當前位置
17: if(event->button() == Qt::LeftButton)
18: {
19: m_CurrentPos = event->globalPos() - T::frameGeometry().topLeft();
20: event->accept();
21: }
22: T::mousePressEvent(event);
23: }
24:
25: void mouseMoveEvent(QMouseEvent *event)
26: {
27: //支持窗體移動
28: if (event->buttons() & Qt::LeftButton)
29: {
30: T::move(event->globalPos() - m_CurrentPos);
31: event->accept();
32: }
33: T::mouseMoveEvent(event);
34: }
35: private:
36: QPoint m_CurrentPos;
37: };
?
接下來我們實現一個圖片按鈕:
1: #include <QPushButton>
2: #include "widgetmove.h"
3:
4: //間接繼承QPushButton,讓按鈕支持移動
5: class ImgButton : public QPushButton
6: {
7: Q_OBJECT
8: public:
9: explicit ImgButton(QWidget *parent = 0);
10: void paintEvent(QPaintEvent *event);
11: QPixmap m_Pixmap;
12: };
13:
14:
15: #include "imgbutton.h"
16: #include <QIcon>
17: #include <QBitmap>
18:
19: ImgButton::ImgButton(QWidget *parent) :
20: QPushButton(parent)
21: {
22: //必須設置為無邊框,否則可見區域和圖片繪制區域將出現不重疊
23: setWindowFlags( Qt::FramelessWindowHint );
24: m_Pixmap.load("close.png");
25: resize(100,100);
26: m_Pixmap = m_Pixmap.scaled(this->size(),Qt::IgnoreAspectRatio);
27: }
28:
29: void ImgButton::paintEvent(QPaintEvent *event)
30: {
31: //繪制背景圖片
32: QIcon icon(m_Pixmap);
33: this->setIcon(icon);
34: this->setIconSize(size());
35: //將png圖片透明部分設置為穿透
36: this->setMask(m_Pixmap.mask());
37: //繪制
38: QPushButton::paintEvent(event);
39: }
然后我們把異形窗體重新實現了:
1: #include <QString>
2: #include <QBitmap>
3: #include <QPaintEvent>
4: #include <QPalette>
5: //異形窗體實現
6:
7: //T 為基類,繼續擁有一個QWidget *parent參數的構造函數
8: template <typename T>
9: class WidgetRuleless : public T
10: {
11: public:
12: WidgetRuleless(QWidget *parent = 0):T(parent)
13: {
14: //設置為無邊框
15: T::setWindowFlags( Qt::FramelessWindowHint );
16: }
17: void SetBackgroundImg(const QString &imgFile)
18: {
19: m_Pixmap.load(imgFile);
20:
21: //保持圖片跟界面一樣大小
22: m_Pixmap = m_Pixmap.scaled(T::size());
23:
24: T::setAutoFillBackground(true);
25:
26: //不規則窗口的關鍵,將圖片透明的地方設為穿透
27: T::setMask( m_Pixmap.mask() );
28: }
29: protected:
30: void paintEvent(QPaintEvent *event)
31: {
32: if(!m_Pixmap.isNull())
33: {
34: //繪制背景圖片
35: QPalette bgPalette = this->palette();
36: bgPalette.setBrush(QPalette::Background,m_Pixmap);
37: T::setPalette(bgPalette);
38: }
39: }
40:
41: private:
42: QPixmap m_Pixmap;
43: };
?
組件準備好后,我們就可以輕松的使用了
1: //創建一個異形窗體,支持move操作,基類為QWidget
2: WidgetRuleless< WidgetMove<QWidget> > wid;
3: wid.SetBackgroundImg("hudie.png");
4: wid.resize(640, 480);
5: //創建一個Button類,并且支持move操作
6: WidgetMove<ImgButton> btn(&wid);
7: btn.move(300,300);
8: wid.show();
?
簡單幾行代碼,我們就可以得到以下效果:
效果圖: 蝴蝶為異形窗體,小樹為異形按鈕,并且都支持move動作。
?
這里我們將經常用的小功能(主要是需要通過繼承實現的),分解成若干小零件,在日常項目開發中,我們只需要進行簡單的組合,就可以得到一個功能強大的控件。
后記:C++是一門異常強大的語言,模板的注入更為C++添加了無窮的潛力,十余年來,他的潛力不斷被挖掘出來,但依舊有存在巨大的潛力等待我們去探索,去發現。
?
注:模板類中不支持Qt信號和槽的機制。
轉載于:https://www.cnblogs.com/lingluotianya/p/4430190.html
總結
- 上一篇: 光遇亲吻飘爱心动作怎么获得?
- 下一篇: ZBar与ZXing使用后感觉