Qt自定義控制元件DLL檔案生成及使用
一、Qt自定義控制元件的制作
參照我的上一篇博客:Qt自定義控制元件繪制儀表盤
這一次需要生成DLL檔案,所以創建的檔案流程有不同,創建程序如下:
1 新建專案:







專案新建完成!
2 在dialplate.h中添加如下代碼
#ifndef DIALPLATE_H
#define DIALPLATE_H
#include <QWidget>
#include<QPainter>
class _declspec(dllexport) DialPlate : public QWidget
{
Q_OBJECT
public:
DialPlate(QWidget *parent = 0);
~DialPlate();
void paintEvent(QPaintEvent *event);//系統自動呼叫
int getBigDivided() const;
void setBigDivided(int value);
int getSmallDivided() const;
void setSmallDivided(int value);
int getScale() const;
void setScale(int value);
int getValue() const;
void setValue(int value);
private:
double centerRadius;//表盤中心圓半徑
double inRadius;//表盤內圓半徑
double midRadius;//表盤中間圓半徑
double outRadius;//表盤最外圓半徑
int bigDivided;//大刻度等分數
int smallDivided;//小刻度等分數
int scale;//倍率
int scaleCount;//scale的位數
int value;//刻度盤的值
void SetParamsInit();
void SetOtherBackground(QPainter *painter);
void DrawPlate(QPainter *painter);
void DrawRing(QPainter *painter,QColor backColor, QColor ringColor,double inRadius,double outRadius);
void DrawScale(QPainter *painter);
void DrawText(QPainter *painter);
void DrawNeedle(QPainter *painter);
void DrawArcRing(QPainter *painter);
void DrawValue(QPainter *painter);
};
#endif
3 在dialplate.cpp中添加如下代碼
#include "dialplate.h"
#include"math.h"
#include<QDebug>
#include<cmath>
DialPlate::DialPlate(QWidget *parent) :
QWidget(parent)
{
bigDivided=10;
smallDivided=10;
scale=1;
scaleCount=1;
value=0;
}
DialPlate::~DialPlate()
{
}
void DialPlate::paintEvent(QPaintEvent *event)
{
QPainter painter(this);//宣告一個畫家物件
painter.setRenderHint(QPainter::Antialiasing);//抗鋸齒形
//初始化引數設定
this->SetParamsInit();
//填充表盤周圍為透明色
this->SetOtherBackground(&painter);
//畫表盤
this->DrawPlate(&painter);
}
int DialPlate::getValue() const
{
return value;
}
void DialPlate::setValue(int value)
{
this->value = value;
}
int DialPlate::getScale() const
{
return scale;
}
void DialPlate::setScale(int value)
{
this->scale = value;
}
int DialPlate::getSmallDivided() const
{
return smallDivided;
}
void DialPlate::setSmallDivided(int value)
{
this->smallDivided = value;
}
int DialPlate::getBigDivided() const
{
return bigDivided;
}
void DialPlate::setBigDivided(int value)
{
this->bigDivided = value;
}
//初始化引數設定
void DialPlate::SetParamsInit()
{
centerRadius=(this->width()-290/340.0*this->width())/2;
inRadius=(this->width()-76/340.0*this->width())/2;
midRadius=(this->width()-38/340.0*this->width())/2;
outRadius=(this->width()-14/340.0*this->width())/2;
}
//設定表盤周圍為透明色
void DialPlate::SetOtherBackground(QPainter *painter)
{
painter->save();
painter->setBrush(Qt::transparent);
painter->fillRect(this->rect(),QColor(0,0,0,0));
painter->restore();
}
//畫表盤
void DialPlate::DrawPlate(QPainter *painter)
{
//畫最外環
DrawRing(painter,QColor(240,240,240), QColor(100,100,100),midRadius,outRadius);
//畫中間黑環
DrawRing(painter,QColor(240,240,240), QColor(0,0,0),inRadius,midRadius);
//畫小環
DrawRing(painter,QColor(240,240,240), QColor(100,100,100),centerRadius,inRadius);
//畫刻度
DrawScale(painter);
//畫黃色指示條
DrawArcRing(painter);
//畫中心點圓
DrawRing(painter,QColor(240,240,240), QColor(233,123,90),0,centerRadius);
//畫數字
DrawText(painter);
//畫指標
DrawNeedle(painter);
//畫值
DrawValue(painter);
}
//畫圓環
void DialPlate::DrawRing(QPainter *painter,QColor backColor, QColor ringColor, double inRadius, double outRadius)
{
QBrush qbrush(ringColor);
painter->setBrush(qbrush);
painter->drawEllipse(QPointF(this->width()/2.0,this->height()/2.0),outRadius,outRadius);
qbrush.setColor(backColor);
painter->setBrush(qbrush);
painter->drawEllipse(QPointF(this->width()/2.0,this->height()/2.0),inRadius,inRadius);
}
//畫刻度
void DialPlate::DrawScale(QPainter *painter)
{
QPen qpen(Qt::white);
double startRadius;//起點半徑
double endRadius=midRadius;//終點半徑
//繪制刻度
for(int i=0;i<=bigDivided*smallDivided;i++)
{
if(i%smallDivided==0)
{
startRadius=inRadius;//大刻度
qpen.setWidthF(2.5);
}
else
{
startRadius=inRadius+(midRadius-inRadius)/2;//小刻度
qpen.setWidthF(1.5);
}
painter->setPen(qpen);
//起點坐標
double xPosStart=this->width()/2+startRadius*cos(3.14*3/4+i*3.14*3/2/bigDivided/smallDivided);
double yPosStart=this->height()/2+startRadius*sin(3.14*3/4+i*3.14*3/2/bigDivided/smallDivided);
//終點坐標
double xPosEnd=this->width()/2+endRadius*cos(3.14*3/4+i*3.14*3/2/bigDivided/smallDivided);
double yPosEnd=this->height()/2+endRadius*sin(3.14*3/4+i*3.14*3/2/bigDivided/smallDivided);
painter->drawLine(QPointF(xPosStart,yPosStart),QPointF(xPosEnd,yPosEnd));
}
}
//畫數字
void DialPlate::DrawText(QPainter *painter)
{
//計算scale是幾位數
int scaleCount=1;
int tempScale=scale;
while (tempScale/10)
{
scaleCount++;
tempScale/=10;
}
int fontSize=30-3*scaleCount;
QPen qpen(Qt::green);
qpen.setWidthF(1.0);
painter->setPen(qpen);
QFont font=painter->font();
font.setPixelSize(fontSize);
painter->setFont(font);
double textRadius=inRadius-30;
for(int i=0;i<=bigDivided;i++)
{
double xPosText=this->width()/2+textRadius*cos(3.14*3/4+i*3.14*3/2/bigDivided);
double yPosText=this->height()/2+textRadius*sin(3.14*3/4+i*3.14*3/2/bigDivided);
QRectF textQRect(xPosText-25,yPosText-12,50,24);
painter->drawText(textQRect,Qt::AlignCenter,QString::number(i*scale));
}
}
//畫指標
void DialPlate::DrawNeedle(QPainter *painter)
{
double needleRadius=this->width()/2-90/340.0*this->width();
double needleCenterRadius=centerRadius-16/340.0*this->width();
//畫指標的圓
DrawRing(painter,Qt::red, Qt::red,0,needleCenterRadius+4);
double biggestValue=bigDivided*scale;
//超出量程則顯示為最大值
if(value>biggestValue)
{
value=bigDivided*scale;
}
//指標三角形的三個點坐標
double xPosNeedle0=this->width()/2+needleRadius*cos(3.14*3/4+value/biggestValue*3.14*3/2);
double yPosNeedle0=this->height()/2+needleRadius*sin(3.14*3/4+value/biggestValue*3.14*3/2);
double xPosNeedle1=this->width()/2+needleCenterRadius*cos(3.14*3/4+value/biggestValue*3.14*3/2+3.14/2);
double yPosNeedle1=this->height()/2+needleCenterRadius*sin(3.14*3/4+value/biggestValue*3.14*3/2+3.14/2);
double xPosNeedle2=this->width()/2+needleCenterRadius*cos(3.14*3/4+value/biggestValue*3.14*3/2-3.14/2);
double yPosNeedle2=this->height()/2+needleCenterRadius*sin(3.14*3/4+value/biggestValue*3.14*3/2-3.14/2);
//畫三角形
QPen qpen(Qt::red);
QBrush qbrush(Qt::red);
painter->setPen(qpen);
painter->setBrush(qbrush);
QPointF points[3]={QPointF(xPosNeedle0,yPosNeedle0),QPointF(xPosNeedle1,yPosNeedle1),
QPointF(xPosNeedle2,yPosNeedle2)};
painter->drawPolygon(points,3);
}
//畫黃色刻度條上的環形指示帶(兩個扇形相減)
void DialPlate::DrawArcRing(QPainter *painter)
{
//畫黃色扇形
if(value>bigDivided*scale)
{
value=bigDivided*scale;
}
QBrush qbrush(QColor(255,255,0,100));
QPen qpen(QColor(255,255,0,100));
painter->setBrush(qbrush);
painter->setPen(qpen);
QRectF outRect(19/340.0*this->width(),19/340.0*this->height(),2*midRadius,2*midRadius);
int startAngle=225*16;
int endAngle=(int)(225+(value/(double)(bigDivided*scale))*270)*16;
int spanAngle=startAngle-endAngle;//角度差(默認為逆時針,負數則為順時針)
painter->drawPie(outRect,startAngle,spanAngle);
//畫減去部分的扇形
QRectF inRect(38/340.0*this->width(),38/340.0*this->height(),2*inRadius,2*inRadius);
qbrush.setColor(QColor(100,100,100));
qpen.setColor(QColor(100,100,100));
painter->setBrush(qbrush);
painter->setPen(qpen);
painter->drawPie(inRect,startAngle,spanAngle+(-16));//為了完全減去黃色內部區域,多減一個單位(16)
}
//在表盤上顯示數值
void DialPlate::DrawValue(QPainter *painter)
{
//計算scale是幾位數
int scaleCount=1;
int tempScale=scale;
while (tempScale/10)
{
scaleCount++;
tempScale/=10;
}
int fontSize=30-3*scaleCount;
QBrush qbrush(Qt::blue);
QPen qpen(Qt::blue);
QFont font=painter->font();
font.setPixelSize(fontSize);
painter->setFont(font);
painter->setBrush(qbrush);
painter->setPen(qpen);
QRectF valueRect(this->width()/2-25,this->height()/2+90/340.0*this->width(),50,30);
painter->drawText(valueRect,Qt::AlignCenter,QString::number(value));
}
4 添加圖示資源

5 選擇構建模式
這里有四種方式,對應以后在四種情況下使用:以后使用的時候要位數(32bit/64bit)和Debug/Release要和自己使用的專案對應起來,這里我們四種都生成一下,后面方便使用,

生成四個檔案夾

6 有用檔案
檔案夾里大概就是這些檔案,我們需要用的就是選擇的兩個(對比Debug和Release生成的檔案有細微差別,Degbug檔案后面多了一個d),再加上源檔案夾里的dialplate.h檔案


自定義控制元件DLL檔案創建完畢
二、DLL檔案的使用
1 QtCreator使用DLL檔案
Qt自帶的QtCreator默認是32bit,所以要直接在Qt中使用的話我目前只能使用32bit的DLL檔案,如果有大神能夠用64bit的DLL方法希望評論區一起交流一下,將32bit/release版本的.dll檔案復制到QtCreator的路徑下,然后打開Qt就可以看到控制元件了(無需將32bit/debug版本的放入,QtCreator只支持32bit/release版本的.dll檔案),
32bit/release版本的dialplateplugin.dll到designer,然后重新打開Qt,就可以看到自定義控制元件,拖到Ui界面也正常顯示,


如果將release和debug的DLL檔案同時放入,debug的DLL檔案不能正常加載,

點擊工具->From Editor->About Qt Designer Plugins

將dialpalte.h、dialplateplugin.lib(release版本)和dialplateplugind.lib(debug版本)檔案放入專案的原始碼檔案夾,

將dialplate.h添加到專案中,

將dialplateplugin.lib添加到外部庫中,注意紅色打鉤地方,這保證專案不僅可以release,還能debug,


添加完成后.pro檔案自動添加了如下代碼,

運行release版本專案,會提示例外結束,將dialplateplugin.dll檔案復制到構建檔案夾類的release檔案夾內,再次運行,完美!


運行debug版本專案,會提示例外結束,將dialplateplugind.dll檔案復制到構建檔案夾類的debug檔案夾內,再次運行,同樣完美!


2 Qt的designer使用DLL檔案
Qt安裝時我們需要安裝這兩個msvc2015(分別是32bit和64bit),在這里32bit和64bit的DLL檔案我們都可以使用了,

將32bit版本的DLL檔案復制到對應的檔案夾內(只需要復制release版本),打開對應的designer.exe,就可以看到我們的自定義控制元件已經加載了,



通過幫助->關于插件查看DLL檔案的加載情況

將64bit版本的DLL檔案復制到對應的檔案夾內(只需要復制release版本),打開對應的designer.exe,就可以看到我們的自定義控制元件已經加載了,



點擊幫助->關于插件,這里會顯示DLL檔案的加載狀態,

至此我們的自定義控制元件就配置完畢啦!
三、在VS2015中創建QT程式,測驗如何使用DLL檔案
如何配置VS2015和QT網上有許多教程,大家一搜就知道了,
1 建立32bit的VS+QT聯合專案
1.1 選擇默認的QT版本(32bit/64it),這里選擇32bit版本,即msvc2015

1.2 新建專案


1.3 分別配置debug和release兩種模式下程式的包含檔案和庫檔案路徑,以及依賴項
debug模式,依賴項的檔案名為:dialplateplugind.lib


release模式,依賴項的檔案名為:dialplateplugin.lib


將dialpalte.h、dialplateplugin.lib和dialplateplugind.libd檔案復制到專案的原始碼檔案夾內

將dialpalte.h添加到程式內

生成解決方案,然后將dialplateplugind.dll和dialplateplugin.dll分別放到對應的Debug和Release檔案夾里



點擊下圖.h檔案,

qt-desinger被打開,將自定義控制元件拖到ui界面上,大小設定為300*300,然后保存并關閉,

重新生成專案后啟動專案,完美運行!

2 建立64bit的VS+QT聯合專案

將箭頭指的地方修改為如圖所示





復制檔案

添加dialplate.h檔案到專案

分別生成debug和release專案,然后將dialplateplugind.dll和dialplateplugin.dll分別復制到x64檔案夾下的
Debug和Release檔案夾內,


點擊圖中檔案,打開qt-designer,將自定義控制元件拖到ui界面上,


重新分別生成專案,點擊本地Windows除錯器,完美運行!

這篇文章我寫得也夠長的,希望對大家有幫助,同時對不足的地方在評論區提出來,謝謝啦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/226327.html
標籤:其他
上一篇:天池 在線編程 分割陣列
