qt自定义时间选择控件窗口

效果如图:

在这里插入图片描述
布局如图:

在这里插入图片描述
参考代码:

//DateTimeSelectWidget
#ifndef DATETIMESELECTWIDGET_H
#define DATETIMESELECTWIDGET_H#include <QWidget>
#include <QDateTime>namespace Ui {
class DateTimeSelectWidget;
}class DateTimeSelectWidget : public QWidget
{Q_OBJECTpublic:explicit DateTimeSelectWidget(QWidget *parent = nullptr);~DateTimeSelectWidget();protected:void showEvent(QShowEvent *event);private:void init_wid_ui();void init_signal_and_slot();signals:void signal_snd_time_update(QString);private slots:void slot_btn_ok_clicked();void slot_update_cur_time_val(int val);private:Ui::DateTimeSelectWidget *ui;
};#endif
#include "datetimeselectwidget.h"
#include "ui_datetimeselectwidget.h"
#include "rollingtimewidget.h"DateTimeSelectWidget::DateTimeSelectWidget(QWidget *parent) :QWidget(parent),ui(new Ui::DateTimeSelectWidget)
{ui->setupUi(this);init_wid_ui();init_signal_and_slot();
}DateTimeSelectWidget::~DateTimeSelectWidget()
{delete ui;
}void DateTimeSelectWidget::showEvent(QShowEvent *event)
{QPushButton *btn = qobject_cast<QPushButton *>(parent());QString curDateTime = btn->text();QStringList list = curDateTime.split(" ");if(list.size() != 2)return;QString date = list[0];QString time = list[1];QStringList datelist = date.split("-");QStringList timelist = time.split(":");if(datelist.size()!=3 || timelist.size()!=3)return;ui->calendarWidget->setSelectedDate(QDate().fromString(date, "yyyy-MM-dd"));ui->wid_hour_select->setCurrTimeVal(QString(timelist[0]).toInt());ui->wid_minute_select->setCurrTimeVal(QString(timelist[1]).toInt());ui->wid_second_select->setCurrTimeVal(QString(timelist[2]).toInt());QWidget::showEvent(event);
}void DateTimeSelectWidget::init_wid_ui()
{this->setWindowFlags(Qt::FramelessWindowHint | Qt::CustomizeWindowHint);//设置时分秒的范围ui->wid_hour_select->setTimeRange(0,23);ui->wid_minute_select->setTimeRange(0,59);ui->wid_second_select->setTimeRange(0,59);
}void DateTimeSelectWidget::init_signal_and_slot()
{connect(ui->wid_hour_select, SIGNAL(signal_update_cur_time_val(int)), this, SLOT(slot_update_cur_time_val(int)));connect(ui->wid_minute_select, SIGNAL(signal_update_cur_time_val(int)), this, SLOT(slot_update_cur_time_val(int)));connect(ui->wid_second_select, SIGNAL(signal_update_cur_time_val(int)), this, SLOT(slot_update_cur_time_val(int)));connect(ui->btn_ok, SIGNAL(clicked()), this, SLOT(slot_btn_ok_clicked()));
}void DateTimeSelectWidget::slot_btn_ok_clicked()
{QDate curDate = ui->calendarWidget->selectedDate();if(curDate.isValid()){QString curDateTime = curDate.toString("yyyy-MM-dd");emit signal_snd_time_update(curDateTime);this->close();}
}void DateTimeSelectWidget::slot_update_cur_time_val(int val)
{QStringList list = ui->lab_hour_minute_second->text().split(":");if(list.size() != 3)return;RollingTimeWidget *wid = qobject_cast<RollingTimeWidget *>(sender());if(wid == ui->wid_hour_select){ui->lab_hour_minute_second->setText(QString("%1:%2:%3").arg(val).arg(list[1]).arg(list[2]));}else if(wid == ui->wid_minute_select){ui->lab_hour_minute_second->setText(QString("%1:%2:%3").arg(list[0]).arg(val).arg(list[2]));}else if(wid == ui->wid_second_select){ui->lab_hour_minute_second->setText(QString("%1:%2:%3").arg(list[0]).arg(list[1]).arg(val));}
}
//RollingTimeWidget
#ifndef ROLLINGTIMEWIDGET_H
#define ROLLINGTIMEWIDGET_H#include <QWidget>
#include <QMouseEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <QDateTime>
#include <QDebug>class RollingTimeWidget : public QWidget
{Q_OBJECT/* 将采用动画的对象属性注册到QT中去,否则动画将无法执行 */Q_PROPERTY(int posYShifting READ PosYShifting WRITE setPosYShifting)public:explicit RollingTimeWidget(QWidget *parent = nullptr);~RollingTimeWidget();/*** @brief setTimeRange 重新设置显示小时范围函数方法* @param int hour最小值* @param int hour最大值* @return void 无*/void setTimeRange(int min,int max); //设置重新设置范围/*** @brief PosYShifting 获取偏移量* @return int posYShifting*/int PosYShifting();/*** @brief setPosYShifting 设置偏移量* @param int 偏移量设置值* @return void 无*/void setPosYShifting(int posYShifting);void setCurrTimeVal(int val);protected:/*** @brief mousePressEvent 重写鼠标按压事件,鼠标拖动进行滚动* @param QMouseEvent* 鼠标按压事件* @return void 无*/void mousePressEvent(QMouseEvent *event)            override;/*** @brief wheelEvent 重写滚轮事件,滚轮进行滚动* @param QWheelEvent* 滚轮事件* @return void 无*/void wheelEvent(QWheelEvent *event)                 override;/*** @brief mouseMoveEvent 重写鼠标移动事件,鼠标移动进入滚动判决* @param QMouseEvent* 鼠标移动事件* @return void 无*/void mouseMoveEvent(QMouseEvent *event)             override;/*** @brief mouseReleaseEvent 重写鼠标松开事件,鼠标松开进入结果判决* @param QMouseEvent* 鼠标松开事件* @return void 无*/void mouseReleaseEvent(QMouseEvent *event)          override;/*** @brief paintEvent 重写绘图事件,对hour进行绘制* @param QPaintEvent* 绘图事件* @return void 无*/void paintEvent(QPaintEvent *paint)                 override;/*** @brief drawNumber 画出滚动数字函数* @param QPaintEvent* 画笔类导入* @param int 数字值value* @param int 滚动偏移量offset* @return void 无*/void drawNumber(QPainter &painter,int value,int offset);/*** @brief rollAnimation 滚动动画方法* @return void 无*/void rollAnimation();signals:void signal_update_cur_time_val(int val);private:/* 最小取值 */int min_Range = 0;/* 最大取值 */int max_Range = 0;/* 字体显示大小 */int numberSize = 5;/* 鼠标移动时判决器 */bool rollingJudgment = false;/* 记录按压鼠标时Y方向的初始位置 */int currentPosY = 0;/* 取系统的小时时间作为滚动时间选择的初始值 */int currentTime = 0;/* 当下的Y方向上的偏移量 */int posYShifting = 0;/* 声明一个动画对象 */QPropertyAnimation rollingAni;
};#endif // ROLLINGTIMEWIDGET_H
#include "rollingtimewidget.h"RollingTimeWidget::RollingTimeWidget(QWidget *parent):QWidget(parent)
{/* 去边框,同时保留窗口原有的属性 */this->setWindowFlags(Qt::FramelessWindowHint | windowFlags());;/* 设置背景样式 */this->setStyleSheet("background:white;");/* 设置动画目标 */rollingAni.setTargetObject(this);/* 设置动画目标属性 */rollingAni.setPropertyName("posYShifting");/* 设置动画持续时间 */rollingAni.setDuration(500);/* 设置动画曲线样式 */rollingAni.setEasingCurve(QEasingCurve::OutCirc);
}RollingTimeWidget::~RollingTimeWidget()
{}void RollingTimeWidget::setTimeRange(int min, int max)
{min_Range = min;max_Range = max;update();
}int RollingTimeWidget::PosYShifting()
{/* 注册属性取值函数 */return posYShifting;
}void RollingTimeWidget::setPosYShifting(int posYShifting)
{/* 注册属性赋值函数 */this->posYShifting = posYShifting;update();
}void RollingTimeWidget::setCurrTimeVal(int val)
{currentTime = val;rollAnimation();update();
}void RollingTimeWidget::mousePressEvent(QMouseEvent *event)
{rollingAni.stop();/* 开启鼠标拖动滚动判决 */rollingJudgment = true;/* 刷新按下时鼠标位置 */currentPosY = event->pos().y();
}void RollingTimeWidget::wheelEvent(QWheelEvent *event)
{/* 以滚轮delta值正负性作为判决条件进行判决 */if(event->delta()>0){if(currentTime > min_Range){posYShifting = this->height()/4;}}else{if(currentTime < max_Range){posYShifting = - this->height()/4;}}rollAnimation();update();
}void RollingTimeWidget::mouseMoveEvent(QMouseEvent *event)
{if(rollingJudgment){if((currentTime == min_Range && event->pos().y() >= currentPosY) || (currentTime == max_Range && event->pos().y() <= currentPosY)){return;}else{posYShifting = event->pos().y() - currentPosY;}update();}
}void RollingTimeWidget::mouseReleaseEvent(QMouseEvent *event)
{Q_UNUSED(event);/*拖动判决归位*/if(rollingJudgment){rollingJudgment = false;/* 开启动画 */rollAnimation();}
}void RollingTimeWidget::paintEvent(QPaintEvent *paint)
{Q_UNUSED(paint);/* 创建画笔对象 */QPainter painter(this);/* 画笔抗锯齿操作 */painter.setRenderHint(QPainter::TextAntialiasing);painter.setRenderHint(QPainter::Antialiasing, true);/* 偏移量检测,以1/4高度和取值范围为边界 */if(posYShifting >= height() / 4 && currentTime > min_Range){/* 鼠标起始位置归位,即加上1/4的高度 */currentPosY += height()/4;/* 偏移量归位,即减去1/4的高度 */posYShifting -= height()/4;/* currentTime自减 */currentTime -= 1;}if(posYShifting <= -height() / 4 && currentTime < max_Range){currentPosY -= height() / 4;posYShifting += height() / 4;currentTime += 1;}/* 调用函数画出数字currentTime */drawNumber(painter,currentTime,posYShifting);/* 调用函数画出两侧数字 */if(currentTime != min_Range){drawNumber(painter,currentTime - 1,posYShifting - height() / 4);}if(currentTime != max_Range){drawNumber(painter,currentTime + 1,posYShifting + height() / 4);}/* 调用函数画出两侧数字 */if(posYShifting >= 0 && currentTime - 2 >= min_Range){drawNumber(painter,currentTime - 2,posYShifting - height() / 2);}if(posYShifting <= 0 && currentTime + 2 <= max_Range){drawNumber(painter,currentTime + 2,posYShifting + height() /  2);}/* 画出数字currentTime两侧边框 */painter.setPen(QPen(QColor(70,144,249),2));painter.drawLine(0,height() / 8 * 3,width(),height() / 8 * 3);painter.drawLine(0,height() / 8 * 5,width(),height() / 8 * 5);emit signal_update_cur_time_val(currentTime);
}void RollingTimeWidget::drawNumber(QPainter &painter, int value, int offset)
{/* 通过偏移量控制数字大小size */int size = (this->height() - abs(offset)) / numberSize;/* 通过偏移量控制数字透明度transparency */int transparency = 255 - 510 * abs(offset) / height();/* 通过偏移量控制数字在ui界面占据空间高度height */int height = this->height() / 2 - 3 * abs(offset) / 5;/* 计算数字显示位置 */int y = this->height() / 2 + offset - height / 2;QFont font;/* 设置字体大小 */font.setPixelSize(size);/* 画笔设置字体 */painter.setFont(font);/* 画笔设置颜色 */painter.setPen(QColor(0,0,0,transparency));/* 画笔painter画出文本*/painter.drawText(QRectF(0,y,width(),height),Qt::AlignCenter,(QString::number(value)));
}void RollingTimeWidget::rollAnimation()
{/* 动画判决,达到条件开启相应动画 */if(posYShifting > height() / 8){/* 设置属性动画初始value */rollingAni.setStartValue(height() / 8 - posYShifting);/* 设置属性动画终止value */rollingAni.setEndValue(0);/* currentTime值变更 */currentTime--;}else if(posYShifting > -height() / 8){/* 设置属性动画初始value */rollingAni.setStartValue(posYShifting);/* 设置属性动画终止value */rollingAni.setEndValue(0);}else if(posYShifting < -height() / 8){/* 设置属性动画初始value */rollingAni.setStartValue(-height() / 8 - posYShifting);/* 设置属性动画终止value */rollingAni.setEndValue(0);/* currentTime值变更 */currentTime++;}/* 动画开始 */rollingAni.start();update();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/730668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单链表OJ题:LeetCode--141.环形链表

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下LeetCode中的第141道单链表OJ题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; 数据结构与算法专栏&#xff1a;数据结构与算法 个 …

O2O:Sample Efficient Offline-to-Online Reinforcement Learning

IEEE TKDE 2024 paper Introduction O2O存在策略探索受限以及分布偏移问题&#xff0c;进而导致在线微调阶段样本效率低。文章提出OEMA算法首先使用离线数据训练乐观的探索策略&#xff0c;然后提出基于元学习的优化方法&#xff0c;减少分布偏移并提高O2O的适应过程。 Meth…

OpenHarmony教程指南-自定义通知推送

介绍 本示例主要展示了通知过滤回调管理的功能&#xff0c;使用ohos.notificationManager 接口&#xff0c;进行通知监听回调&#xff0c;决定应用通知是否发送。 效果预览 使用说明 1.在使用本应用时&#xff0c;需安装自定义通知角标应用&#xff1b; 2.在主界面&#xff…

重学SpringBoot3-WebMvcAutoConfiguration类

重学SpringBoot3-WebMvcAutoConfiguration类 是什么什么用生效条件作用 自定义配置的三种方式自定义配置举例1. 自定义 DispatcherServlet 配置2. 静态资源配置3. 自定义MVC配置4. 消息转换器5. 异常处理 是什么 org.springframework.boot.autoconfigure.web.servlet.WebMvcAut…

FPGA IBUFG

IBUFG和IBUFGDS的输入端仅仅与芯片的专用全局时钟输入管脚有物理连接&#xff0c;与普通IO和其它内部CLB等没有物理连接。 所以&#xff0c;IBUFG输入的不能直接接另外信号。 GTH transceiver primitives are called GTHE3_COMMON and GTHE3_CHANNEL in UltraScale FPGAs, an…

@RequestMapping与@GetMapping和@PostMapping等注解的区别

目录 前置知识 大致区别 使用场景上的注意事项 如何工作 使用案例 写法对比 前置知识 HTTP请求方法一共有9种&#xff0c;为&#xff1a;GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECTGET(获取资源) 本质就是发送一个请求来取得服务器上的某一资源&…

【Java代码审计】JNDI+RMI绕过高版本JDK的限制

【Java代码审计】JNDIRMI绕过高版本JDK的限制 1.高版本JDK利用注入导致的问题2.绕过分析3.Tomcat8绕过4.工具绕过 1.高版本JDK利用注入导致的问题 JDK 6u132、7u122、8u113 开始 com.sun.jndi.rmi.object.trustURLCodebase 默认值为false&#xff0c;运行时需加入参数 -Dcom.s…

Go语言物联网开发安科瑞ADW300/4G电能表数据上传mqtt平台-电表接线到传输数据完整流程

电能表功能说明 ADW300是方便用户进行用电监测、集抄和管理&#xff0c;可灵活安装在配电箱中&#xff0c;可用于电力运维、环保监管等在线监测类平台中。我们本案例是用于工业售电公司对出售电的管理&#xff0c;设备可以监控用电情况、故障监控及警报&#xff0c;售电公司可…

(完美方案)解决mfc140u.dll文件丢失问题,快速且有效的修复

唉&#xff0c;又是丢失了mfc140u.dll&#xff0c;这该怎么办呢&#xff1f;如果你的电脑突然找不到或丢失mfc140u.dll文件&#xff0c;那就真是太糟糕了。别担心&#xff0c;我分享给你一些干货&#xff0c;告诉你如何快速解决mfc140u.dll丢失的问题。 一.mfc140u.dll属性功能…

百度地图城市点位数据下载并转换

概述 在浏览百度地图开放平台的时候&#xff0c;发现有个资源下载页面&#xff0c;里面有个城市中心点位和百度地图行政区划adcode映射表数据&#xff0c;这是一个经常使用到的数据&#xff0c;本文实现将这个数据转换为geojson&#xff0c;并借助QGIS转换为经纬度坐标或火星坐…

LCR 175. 计算二叉树的深度

一、题目描述 LCR 175. 计算二叉树的深度 二、思路 递归求左右子树的高度 三、解题思路 把大规模的问题拆分成小规模的问题1、要求根节点的二叉树深度 2、转换子问题&#xff1a;求左子树为根节点的二叉树深度 3、转换子问题&#xff1a;成求右子树为根节点的二叉树深度 4、最…

宏auto关键字(C++基础)

宏 宏可以实现对语句的同义替换&#xff0c;简单来说就是预处理阶段、编译前的替换&#xff08;包括符号&#xff0c;变量等&#xff09;。 #define LOG(x) std::cout << x << std::endl; LOG("hello") 可以正常使用。 下面通过上图中借用不同开发模…

Threejs着色器(GPU)编程——感温管网

管网,作为支撑现代城市运转的重要基础设施,是隐藏在地面之下的庞大工程网络。这些管网如同城市的血脉,负责输送各种必要的资源,如水源、热力、燃气等,同时排除废水和其他废弃物。然而,由于其位于地下,人们往往难以直接感知其存在和运行状态。为了保障这些地下管网的安全…

Leetcode - 周赛387

目录 一&#xff0c;3069. 将元素分配到两个数组中 I 二&#xff0c;3070. 元素和小于等于 k 的子矩阵的数目 三&#xff0c;3071. 在矩阵上写出字母 Y 所需的最少操作次数 四&#xff0c;3072. 将元素分配到两个数组中 II 一&#xff0c;3069. 将元素分配到两个数组中 I 本…

Express学习(三)

Express中间件 中间件的概念 什么是中间件 中间件&#xff0c;特指业务流程的中间处理环节。Express中间件的调用流程 当一个请求到达Express的服务器之后&#xff0c;可以连续调用多个中间件&#xff0c;从而对这次请求进行预处理。类似于下图所示 Express中间件的格式 Expr…

内联函数|auto关键字|范围for的语法|指针空值

文章目录 一、内联函数1.1概念1.2特性 二、auto关键字2.2类型别名思考2.3auto简介2.4auto使用细则2.4 auto不能推导的场景 三、基于范围的for循环(C11)3.1 范围for的语法 四、指针空值nullptr(C11)4.1 C98中的指针空值 所属专栏:C初阶 一、内联函数 1.1概念 以inline修饰的函…

【LeetCode】升级打怪之路 Day 16:二叉树题型 —— 二叉树的构造

今日题目&#xff1a; 654. 最大二叉树105. 从前序与中序遍历序列构造二叉树106. 从中序与后序遍历序列构造二叉树889. 根据前序和后序遍历构造二叉树 目录 LC 654. 最大二叉树 【easy】 Problem&#xff1a;根据遍历序列来还原二叉树 【classic】 ⭐⭐⭐⭐⭐LC 105. 从前序与中…

C++vector的使用方法

文章目录 一、vector的介绍1. 文档链接2. 简要介绍 二、vector的使用1.vector的定义&#xff08;1&#xff09;构造函数&#xff08;2&#xff09;拷贝构造函数&#xff08;2&#xff09;赋值重载 2. vector 增删查改&#xff08;1&#xff09;operator []&#xff08;2&#x…

[HackMyVM]靶场 Quick3

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (U…

HTML—常用标签

常用标签&#xff1a; 标题标签&#xff1a;<h1></h1>......<h6></h6>段落标签&#xff1a;<p></p>换行标签&#xff1a;<br/>列表&#xff1a;无序列表<ul><li></li></ul> 有序列表<ol>&…