Qt实现自定义控件的两种方式之提升法

server/2024/9/24 6:13:42/

一:提升Qt设计师界面类

第一步:添加新文件选择Qt设计师界面类

第二步:选择界面模板

看自己需求,一般不需要怎么更改

第三步:为设计师界面类起一个类名

类名不能全是小写,要不然后面会出错

此时可以添加一些图片资源到项目中,即添加Qt资源文件(图片名字起反了,不改了)

第四步:在设计师界面类ImageSwitch添加一个label

设置label大小,删除label的内容,并更改控件名

第五步:右键label,添加样式表,添加图片资源

点击<resouce root>,选择openSwitch.png(图片名字起反了,不改了),点击ok

操作完可得到

第六步:重写ImageSwitch类的mousePressEvent事件,实现鼠标点击显示动态开关的效果

ImageSwitch.h

#ifndef IMAGESWITCH_H
#define IMAGESWITCH_H#include <QWidget>
#include <QMouseEvent>
namespace Ui {
class ImageSwitch;
}class ImageSwitch : public QWidget
{Q_OBJECTpublic:explicit ImageSwitch(QWidget *parent = nullptr);~ImageSwitch();void mousePressEvent(QMouseEvent* event) override;private:Ui::ImageSwitch *ui;bool m_switchIsOpen;
};#endif // IMAGESWITCH_H

ImageSwitch.cpp

#include "imageswitch.h"
#include "ui_imageswitch.h"ImageSwitch::ImageSwitch(QWidget *parent) :QWidget(parent),ui(new Ui::ImageSwitch)
{ui->setupUi(this);//初始按钮没有被选中m_switchIsOpen = false;
}ImageSwitch::~ImageSwitch()
{delete ui;
}void ImageSwitch::mousePressEvent(QMouseEvent *event)
{if(m_switchIsOpen){m_switchIsOpen = !m_switchIsOpen;ui->lbSwitch->setStyleSheet("image: url(:/openSwitch.png);");}else{m_switchIsOpen = !m_switchIsOpen;ui->lbSwitch->setStyleSheet("image: url(:/closeSwitch.png);");}}

第七步:在项目的ui界面中添加widget控件

右键选择提升到

填写类名时,注意大小写是有区别的,点击添加

选择添加的提升类,点击提升

第八步:编译项目,然后运行

二:提升C++类(没有界面)

这种就是纯在.h和.cpp文件中来创建控件,一般就是重写paintEvent,在paintEvent中使用QPainter和图片资源来进行控件的创建

第一步:新建C++类

名字啥的还是一样不能全小写,继承啥的看自己需求,这里我选的widget

第二步:编写控件代码

Loading.h

#ifndef LOADING_H
#define LOADING_H#include <QWidget>
#include <QPainter>
#include <QTimer>
#include <QMap>struct Location
{
public:explicit Location(float _x,float _y){x=_x;y=_y;}float x;float y;
};class Loading : public QWidget
{Q_OBJECT
public:explicit Loading(QWidget *parent = nullptr);//设置圆点个数void setDotCount(int);//设置点颜色void setDotColor(const QColor&);//开始void start();//设置圆点最大直径void setMaxDiameter(float);//设置圆点最小直径void setMinDiameter(float);//计算void caculate();
protected:void paintEvent(QPaintEvent *event);void resizeEvent(QResizeEvent *event);
signals:private slots:void refresh();private://刷新计数int _index;//点的颜色QColor _dotColor;//点的个数int _count;//圆点最小直径float _minDiameter;//圆点最大直径float _maxDiameter;//绘制圆点void paintDot(QPainter &);//计数int _i;//时间间隔 单位:毫秒(ms)int _interval;//定时器QTimer* timer;//绘制区域边长float _squareWidth;//圆的直径float _centerDistance;//直径列表QList<float> radiiList;//圆点坐标列表QList<Location> locationList;};#endif // LOADING_H

Loading.cpp

#include "Loading.h"
#include <QDebug>
#include <qmath.h>
Loading::Loading(QWidget *parent) : QWidget(parent),_i(0),_interval(50),_index(0)
{//设置背景透明//this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);//this->setAttribute(Qt::WA_TranslucentBackground, true);setDotColor(QColor(49, 177, 190));setDotCount(20);timer = new QTimer(this);connect(timer,&QTimer::timeout,this,&Loading::refresh);setMaxDiameter(30);setMinDiameter(5);
}//********************************************** 设置部分 *************************************
//设置点的个数
void Loading::setDotCount(int count)
{_count=count;
}//设置点的颜色
void Loading::setDotColor(const QColor & color)
{_dotColor=color;
}//开始动画
void Loading::start()
{timer->setInterval(_interval);timer->start();
}//设置最大直径
void Loading::setMaxDiameter(float max)
{_maxDiameter=max;
}//设置最小直径
void Loading::setMinDiameter(float min)
{_minDiameter=min;
}
//********************************************** 绘制部分 *************************************
//刷新界面
void Loading::refresh()
{repaint();
}void Loading::resizeEvent(QResizeEvent *event)
{Q_UNUSED(event)caculate();
}void Loading::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setPen(_dotColor);painter.setBrush(_dotColor);//绘制点paintDot(painter);
}//计算绘制正方形区域
void Loading::caculate()
{_squareWidth=qMin(this->width(),this->height());float half=_squareWidth/2;_centerDistance=half-_maxDiameter/2-1;float gap=(_maxDiameter-_minDiameter)/(_count-1)/2;float angleGap=(float)360/_count;locationList.clear();radiiList.clear();for(int i=0;i<_count;i++){radiiList<<_maxDiameter/2-i*gap;float radian=qDegreesToRadians(-angleGap*i);locationList.append(Location(half+_centerDistance*qCos(radian),half-_centerDistance*qSin(radian)));}
}//绘制圆点
void Loading::paintDot(QPainter& painter)
{for(int i=0;i<_count;i++){painter.setPen(_dotColor);//半径float radii=radiiList.at((_index+_count-i)%_count);//绘制圆点painter.drawEllipse(QPointF(locationList.at(i).x,locationList.at(i).y),radii,radii);//绘制正方形//painter.drawRect(locationList.at(i).x,locationList.at(i).y,radii,radii);}_index++;
}

第三步:在项目的ui界面中添加widget控件

右键选择提升到

选择添加的提升类(这里我已经添加过),点击提升

第四步:编译项目,然后运行

参考

(一)Qt实现自定义控件的两种方式---提升法_qt自定义控件-CSDN博客


http://www.ppmy.cn/server/99734.html

相关文章

Java如何使用 HTTP 请求下载图片

工具类&#xff1a; public FileInputStream fileDownload(String fileLink) throws Exception {System.out.println("开始下载"fileLink);// 转码中文URL url new URL(encodeURLChinese(fileLink));System.out.println("fileLink:"url);// 开始下载Trust…

Redis的六种淘汰策略详解

Redis作为一种高性能的键值对存储系统&#xff0c;其数据全部存储在内存中&#xff0c;因此内存管理对Redis的性能至关重要。当Redis的内存使用达到上限时&#xff0c;就需要通过淘汰策略来释放内存空间&#xff0c;以便存储新的数据。Redis提供了六种不同的淘汰策略&#xff0…

15.2 Scikit-learn简介与常用模型

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 工&#x1f497;重&#x1f497;hao&#x1f497;&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

【第九节】python中xml解析和json编解码

目录 一、Python XML 解析 1.1 什么是XML 1.2 Python 对 XML 的解析方法 1.3 SAX解析xml 1.4 xml.dom解析xml 1.6 ElementTree解析XML 二、Python编解码json 2.1 什么是json 2.2 使用json 库 2.3 使用第三方库Demjson 一、Python XML 解析 1.1 什么是XML XML&#x…

Vue 应用实例的关键方法与配置案例二

目录 createApp createSSRApp app.mount app.unmount app.component app.directive Vue3.X自定义全局指令 Vue2.X自定义全局指令 app.use app.mixin 非 VIP 用户能够免费下载博文资源 createApp 详见上一章节:Vue 应用实例的关键方法与配置案例一-CSDN博客 createSS…

数字化营销利器:企元数智小程序合规分销系统免费获取!

在当今数字化时代&#xff0c;营销策略已经成为企业成功的关键。为了帮助企业更好地实现数字化营销&#xff0c;企元数智小程序合规分销系统应运而生&#xff0c;成为了企业的得力助手。 企元数智小程序合规分销系统集合了先进的科技和创新理念&#xff0c;为企业营销带来了全新…

大厂进阶之二:React高级用法HOC、Hooks对比、异步组件

本文分文三部分&#xff1a; HOC高阶组件 higher order componentHooks 16.8版本后新增的钩子API异步组件使用lazy和suspense两个api实现组件代码打包分割和异步加载 一、HOC高阶组件 1、定义 高阶组件不是组件而是函数&#xff0c;是react中用于复用组件逻辑的高级技巧&am…

【vue教程】五. Vue 的路由管理

目录 往期列表本章涵盖知识点回顾Vue Router 的基本概念什么是 Vue Router&#xff1f;为什么需要 Vue Router&#xff1f; 路由的配置和使用安装 Vue Router创建路由在 Vue 实例中使用路由模板中的路由链接 动态路由和嵌套路由动态路由嵌套路由 路由守卫什么是路由守卫&#x…