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调试器,完美运行!
这篇文章我写得也够长的,希望对大家有帮助,同时对不足的地方在评论区提出来,谢谢啦!