當UI設計器提供的界面組件不滿足實際設計需求時,可以從 QWidget 繼承自定義界面組件。
有兩種方法使用自定義界面組件:
-
一種是
提升法(promotion)
,例如在8.3 節(jié)將一個QGraphicsView組件提升為自定義的 QWGraphicsView 類,提升法用于界面可視化設計時不夠直觀,不能在界面上即刻顯示自定義組件的效果; -
另一種是
為 UI 設計器設計自定義界面組件的 Widget 插件,直接安裝到 UI設計器的組件面板里,如同 Qt 自帶的界面設計組件一樣使用,在設計時就能看到組件的實際顯示效果,只是編譯和運行時需要使用到插件的動態(tài)鏈接庫 (Windows 平臺上)
。
本章先介紹這兩種自定義 Widget 組件的設計和使用方法,再介紹Qt編寫和使用靜態(tài)鏈接庫和共享庫(Windows 平臺上就是動態(tài)鏈接庫)的方法
1. 自定義 Widget 子類QmyBattery
Qt的 UI 設計器提供了很多 GUI 設計的界面組件,可以滿足常見的界面設計需求。但是某些時候需要設計特殊的界面組件,而在 UI設計器的組件面板里根本沒有合適的組件,這時就需要設計自定義的界面組件。
所有界面組件的基類是QWidget,要設計自定義的界面組件,可以從QWidget繼承一個自定義的類,重定義其painEvent()事件,利用Qt的繪圖功能會追組件外觀,并實現(xiàn)所需的其他功能。
例如,假設需要設計一個如下圖所示的電池電量顯示組件,用于電池使用或充電時顯示其電量,但是在 UI 設計器的組件面板里是沒有這樣一個現(xiàn)成的組件的。這就需要設計一個自定義的Widget 組件。
為此,設計一個從QWidget 繼承的類QmyBattery。創(chuàng)建C++類,可以單擊 Qt Creator 的“File”一“New File or Project”菜單項,在出現(xiàn)的對話框里選擇 C++類組里的 C++ Class,在向導中設置類的名稱,并選擇基類為 QWidget。
定義QmyBattery類的qmybattery.h 文件的完整代碼如下:
#ifndef WBATTERY_H
#define WBATTERY_H
#include <QWidget>
#include <QColor>
class QmyBattery : public QWidget
{
Q_OBJECT
//自定義屬性
Q_PROPERTY(int powerLevel READ powerLevel WRITE setPowerLevel NOTIFY powerLevelChanged)
private:
QColor mColorBack=Qt::white;//背景顏色
QColor mColorBorder=Qt::black;//電池邊框顏色
QColor mColorPower=Qt::green;//電量柱顏色
QColor mColorWarning=Qt::red;//電量短缺時的顏色
int mPowerLevel=60;//電量0-100
int mWarnLevel=20;//電量低警示閾值
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
public:
explicit QmyBattery(QWidget *parent = 0);
void setPowerLevel(int pow);//設置當前電量
int powerLevel();
void setWarnLevel(int warn);//設置電量低閾值
int warnLevel();
QSize sizeHint();//報告缺省大小
signals:
void powerLevelChanged(int );
public slots:
};
#endif // WBATTERY_H
在 private 部分定義了幾個私有變量,主要是各種顏色的定義、當前電量值 mPowerLevel 和電量低閾值mWarLevel。
protected 部分重定義了 paintEvent()事件,在第8章中介紹過,QWidget 類的 paintEvent()事件用于界面繪制,在此事件里,可以使用 QPainter 的各種繪圖功能繪制自己需要的界面。
public 部分定義了用于讀取和設置當前電量值、電量低閾值的函數(shù),還定義了 sizeHint()函數(shù)用于返回組件缺省大小。
定義了一個信號 powerLevelChanged(int),在當前電量值改變時發(fā)射該信號,使用QmyBattery類時可以設計槽函數(shù)對此信號做處理。
下面是 QmyBattery 類的實現(xiàn)代碼,復雜一點的部分是 paintEvent()事件函數(shù)里繪制界面的功能實現(xiàn),這里設置了窗口邏輯坐標,所以,當組件大小變化時,繪制的電池大小也會自動變化。QPainter 繪圖的功能在第 8 章有詳細介紹,這里不再詳細解釋。
#include "qmybattery.h"
#include <QPainter>
void QmyBattery::paintEvent(QPaintEvent *event)
{ //界面組件的繪制
Q_UNUSED(event);
QPainter painter(this);
QRect rect(0,0,width(),height()); //viewport矩形區(qū)
painter.setViewport(rect);//設置Viewport
painter.setWindow(0,0,120,50); // 設置窗口大小,邏輯坐標
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);
//繪制電池邊框
QPen pen;//設置畫筆
pen.setWidth(2); //線寬
pen.setColor(mColorBorder); //劃線顏色
pen.setStyle(Qt::SolidLine);//線的類型,實線、虛線等
pen.setCapStyle(Qt::FlatCap);//線端點樣式
pen.setJoinStyle(Qt::BevelJoin);//線的連接點樣式
painter.setPen(pen);
QBrush brush;//設置畫刷
brush.setColor(mColorBack); //畫刷顏色
brush.setStyle(Qt::SolidPattern); //畫刷填充樣式
painter.setBrush(brush);
rect.setRect(1,1,109,48);
painter.drawRect(rect);//繪制電池邊框
brush.setColor(mColorBorder); //畫刷顏色
painter.setBrush(brush);
rect.setRect(110,15,10,20);
painter.drawRect(rect); //畫電池正極頭
//畫電池柱
if (mPowerLevel>mWarnLevel)
{ //正常顏色電量柱
brush.setColor(mColorPower); //畫刷顏色
pen.setColor(mColorPower); //劃線顏色
}
else
{ //電量低電量柱
brush.setColor(mColorWarning); //畫刷顏色
pen.setColor(mColorWarning); //劃線顏色
}
painter.setBrush(brush);
painter.setPen(pen);
if (mPowerLevel>0)
{
rect.setRect(5,5,mPowerLevel,40);
painter.drawRect(rect);//畫電池柱
}
//繪制電量百分比文字
QFontMetrics textSize(this->font());
QString powStr=QString::asprintf("%d%%",mPowerLevel);
QRect textRect=textSize.boundingRect(powStr);//得到字符串的rect
painter.setFont(this->font());
pen.setColor(mColorBorder); //劃線顏色
painter.setPen(pen);
painter.drawText(55-textRect.width()/2,
23+textRect.height()/2,
powStr);
}
QmyBattery::QmyBattery(QWidget *parent) : QWidget(parent)
{
// setPalette(QPalette(mColorBack));
// setAutoFillBackground(true);
// this->resize(120,50);
}
void QmyBattery::setPowerLevel(int pow)
{ //設置當前電量值
mPowerLevel=pow;
emit powerLevelChanged(pow); //觸發(fā)信號
repaint();
}
int QmyBattery::powerLevel()
{ //讀取當前電量值
return mPowerLevel;
}
void QmyBattery::setWarnLevel(int warn)
{//設置電量低閾值
mWarnLevel=warn;
repaint();
}
int QmyBattery::warnLevel()
{//讀取電量低閾值
return mWarnLevel;
}
QSize QmyBattery::sizeHint()
{//報告缺省大小,調整比例
int H=this->height();
int W=H*12/5;
QSize size(W,H);
return size;
}
2. 自定義Widget組件的使用
實現(xiàn)了QmyBattery 類之后,若是用代碼創(chuàng)建QmyBattery 類對象,其使用與一般的組件類是一樣的;若是在 UI設計器中使用 QmyBattery,則需要采用提升法(promotion)。
實例 samp12 1是一個基于 QWidegt 的應用程序,使用 UI 設計器設計主窗體時,在窗體上放置一個QWidegt 類組件,然后鼠標右鍵調出其快捷菜單,單擊“Promote to”菜單項,會出現(xiàn)如下圖所示的對話框。
此對話框里,在基類名稱下拉列表框里選擇 QWidget,將提升后的類名稱設置為 QmyBattery,頭文件名稱會自動生成??梢詫⒃O置添加到已提升類的列表里,以便重復使用。
設置后,單擊“Promote”按鈕,就可以將此QWidget 組件提升為 QmyBattery 類。提升后,在 Property Editor 里會看到這個組件的類名稱變?yōu)榱?QmyBattery。然后,將其 objectName 更改為 battery。
雖然界面上放置的 QWidget 組件被提升為了 QmyBattery 類,但是在這個組件的“Go to slot’對話框里并沒有QmyBattery 類的 powerLevelChanged(int) 信號,無法采用可視化方法生成信號的槽函數(shù)。
在主窗口上放置一個 QSlider 組件和一個 QLabel 組件?;瑒訕顺吒淖償?shù)值時,設置為 battery的當前電量值,其 valueChanged()信號的槽函數(shù)代碼如下:
void Widget::on_horizontalSlider_valueChanged(int value)
{
ui->battery->setPowerLevel(value);
QString str=QStringLiteral("當前電量:")+QString::asprintf("%d %%",value);
ui->LabInfo->setText(str);
}
battery 的各種參數(shù)采用其缺省的設置,battery 的當前電量值改變時,內部會調用 paintEvent()事件代碼重新繪制電池顯示效果。
3. 軟件結構及源代碼
3.1 軟件結構
3.2 可視化UI設計
3.3 源碼
(1)qmybattery.h
#ifndef WBATTERY_H
#define WBATTERY_H
#include <QWidget>
#include <QColor>
class QmyBattery : public QWidget
{
Q_OBJECT
//自定義屬性
Q_PROPERTY(int powerLevel READ powerLevel WRITE setPowerLevel NOTIFY powerLevelChanged)
private:
QColor mColorBack=Qt::white;//背景顏色
QColor mColorBorder=Qt::black;//電池邊框顏色
QColor mColorPower=Qt::green;//電量柱顏色
QColor mColorWarning=Qt::red;//電量短缺時的顏色
int mPowerLevel=60;//電量0-100
int mWarnLevel=20;//電量低警示閾值
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
public:
explicit QmyBattery(QWidget *parent = 0);
void setPowerLevel(int pow);//設置當前電量
int powerLevel();
void setWarnLevel(int warn);//設置電量低閾值
int warnLevel();
QSize sizeHint();//報告缺省大小
signals:
void powerLevelChanged(int );
public slots:
};
#endif // WBATTERY_H
(2)qmybattery.cpp文章來源:http://www.zghlxwxcb.cn/news/detail-615333.html
#include "qmybattery.h"
#include <QPainter>
void QmyBattery::paintEvent(QPaintEvent *event)
{ //界面組件的繪制
Q_UNUSED(event);
QPainter painter(this);
QRect rect(0,0,width(),height()); //viewport矩形區(qū)
painter.setViewport(rect);//設置Viewport
painter.setWindow(0,0,120,50); // 設置窗口大小,邏輯坐標
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);
//繪制電池邊框
QPen pen;//設置畫筆
pen.setWidth(2); //線寬
pen.setColor(mColorBorder); //劃線顏色
pen.setStyle(Qt::SolidLine);//線的類型,實線、虛線等
pen.setCapStyle(Qt::FlatCap);//線端點樣式
pen.setJoinStyle(Qt::BevelJoin);//線的連接點樣式
painter.setPen(pen);
QBrush brush;//設置畫刷
brush.setColor(mColorBack); //畫刷顏色
brush.setStyle(Qt::SolidPattern); //畫刷填充樣式
painter.setBrush(brush);
rect.setRect(1,1,109,48);
painter.drawRect(rect);//繪制電池邊框
brush.setColor(mColorBorder); //畫刷顏色
painter.setBrush(brush);
rect.setRect(110,15,10,20);
painter.drawRect(rect); //畫電池正極頭
//畫電池柱
if (mPowerLevel>mWarnLevel)
{ //正常顏色電量柱
brush.setColor(mColorPower); //畫刷顏色
pen.setColor(mColorPower); //劃線顏色
}
else
{ //電量低電量柱
brush.setColor(mColorWarning); //畫刷顏色
pen.setColor(mColorWarning); //劃線顏色
}
painter.setBrush(brush);
painter.setPen(pen);
if (mPowerLevel>0)
{
rect.setRect(5,5,mPowerLevel,40);
painter.drawRect(rect);//畫電池柱
}
//繪制電量百分比文字
QFontMetrics textSize(this->font());
QString powStr=QString::asprintf("%d%%",mPowerLevel);
QRect textRect=textSize.boundingRect(powStr);//得到字符串的rect
painter.setFont(this->font());
pen.setColor(mColorBorder); //劃線顏色
painter.setPen(pen);
painter.drawText(55-textRect.width()/2,
23+textRect.height()/2,
powStr);
}
QmyBattery::QmyBattery(QWidget *parent) : QWidget(parent)
{
// setPalette(QPalette(mColorBack));
// setAutoFillBackground(true);
// this->resize(120,50);
}
void QmyBattery::setPowerLevel(int pow)
{ //設置當前電量值
mPowerLevel=pow;
emit powerLevelChanged(pow); //觸發(fā)信號
repaint();
}
int QmyBattery::powerLevel()
{ //讀取當前電量值
return mPowerLevel;
}
void QmyBattery::setWarnLevel(int warn)
{//設置電量低閾值
mWarnLevel=warn;
repaint();
}
int QmyBattery::warnLevel()
{//讀取電量低閾值
return mWarnLevel;
}
QSize QmyBattery::sizeHint()
{//報告缺省大小,調整比例
int H=this->height();
int W=H*12/5;
QSize size(W,H);
return size;
}
(3) widget.cpp文章來源地址http://www.zghlxwxcb.cn/news/detail-615333.html
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_horizontalSlider_valueChanged(int value)
{
ui->battery->setPowerLevel(value);
QString str=QStringLiteral("當前電量:")+QString::asprintf("%d %%",value);
ui->LabInfo->setText(str);
}
到了這里,關于12-1_Qt 5.9 C++開發(fā)指南_自定義插件和庫-自定義Widget組件(提升法(promotion)創(chuàng)建自定義定制化組件)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!