(二)Qt实现自定义控件的两种方式---插件法

系列文章目录

(一)Qt实现自定义控件的两种方式—提升法
(二)Qt实现自定义控件的两种方式—插件法



前言

上一篇文章提到了使用提升法来实现自定义控件的创建,但是在使用过程中往往需要运行后才能看到自定义控件的效果,这就不太方便了。本文主要讲述了插件法来实现自定义控件,将其插入至你的Qt设计师界面里面,这样能够更直观的看到你的自定义控件。

参考博客地址:Qt自定义控件DLL文件生成及使用

在博客编写过程中,发现这个大佬的博客写的非常详细,建议转至原博文进行查看,本文按照其中的流程并引用了其中的代码,最后完成了项目效果图中的自定义控件。这边总结下跟随过程中发现的问题及解决方法

项目效果

1.Qt设计师界面
请添加图片描述

2.运行效果
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、Qt自定义控件的制作/完整代码

1.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

2.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));
}

二、QtCreator使用DLL文件/问题解决

1.按照参考博客进行自定义控件的创建,在完成代码修改后,编译出现如下问题
请添加图片描述

2.我这边出现该问题的原因是忘记在pro文件中添加.h文件,所以在项目pro文件中添加如下语句,问题解决编译通过

HEADERS += \
    dialplate.h 

总结

本文根据参考博客完成了插件法实现自定义控件,总结了这个过程中可能出现的问题及解决方法。Qt的自定义控件的好处在于可以扩展Qt没有的控件,提升法可以随时进行代码修改以及接口引出,但是无法直观的显示,插件法使用DLL可以方便查看及调用,但是接口相对固定。所以不管使用哪种方法,最重要的还是结合项目实际情况来进行开发。

上一篇:(一)Qt实现自定义控件的两种方式—提升法


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考博客:Qt自定义控件DLL文件生成及使用

  • 18
    点赞
  • 102
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Qt中的setViewport方可以用于设置QAbstractScrollArea和QGraphicsView的视口大小和位置。它通常与setWidget或setScene方一起使用以创建可滚动视图。 如果你想要使用setViewport实现缩放,你需要考虑以下几点: 1. 首先,你需要确定视口的大小和位置。 2. 然后,你需要确定如何缩放视口中的内容。你可以使用QTransform类的scale方来缩放内容。 3. 最后,你需要将缩放后的内容设置为视口的widget或scene。 下面是一个使用setViewport实现缩放的示例代码片段: ``` QGraphicsView *view = new QGraphicsView(this); view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); view->setRenderHint(QPainter::Antialiasing); view->setDragMode(QGraphicsView::ScrollHandDrag); view->setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing); view->setInteractive(true); view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QGraphicsScene *scene = new QGraphicsScene(view); view->setScene(scene); QPixmap pixmap(":/images/image.png"); QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap); scene->addItem(item); QTransform transform; transform.scale(2, 2); item->setTransform(transform); view->setSceneRect(item->boundingRect()); ``` 在这个例子中,我们使用QGraphicsView创建了一个视口,并为其设置了一些属性。然后,我们创建了一个QGraphicsScene,并将其设置为视口的scene。接下来,我们创建了一个QGraphicsPixmapItem,并将其添加到场景中。最后,我们使用QTransform类的scale方将QGraphicsPixmapItem缩放了两倍,并将其设置为场景的边界矩形。 请注意,这只是一个简单的示例,实际上实现缩放可能需要更多的代码。同时,缩放可能会使内容变得模糊或失真,因此你需要找到一个合适的缩放比例来平衡视觉效果和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值