当前位置: 首页 > news >正文

Qt C++ 开发 动态上下页按钮实现

项目开发,想实现动态的显示按钮,考虑使用QStackedWidget做两个页面去切换。

首先,我们使用Qt ui 画出两个QStackedWidget的两个页面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
要实现切换,我们只需要调用stackedWidget->setCurrentIndex(index)就行。
那么如何自动调用呢?
这时候,我们想到网页的正常操作。当鼠标在某个区悬浮超过固定时间时,将按钮显示出来,也就是切换页面。
这里我们遇到了个坑, Qt为了缩减资源消耗,只在鼠标按下才触发mouseMoveEvent!
切记修改MouseTracking属性,我们修改了整个ui的MouseTracking属性发现没有用???
查资料,需要将所有QWidget子节点全部赋值!

void setMouseTrackingRecursively(QWidget* widget) {if (widget == nullptr)return;widget->setMouseTracking(true);const QObjectList& children = widget->children();for (QObject* child : children) {if (child->isWidgetType()) {setMouseTrackingRecursively(qobject_cast<QWidget*>(child));}}
}

实现完成,发现还行,但是缺少点灵魂,动画太直接了。
好的,加动画属性:#include <QPropertyAnimation>
这玩意太多功能了,后期单独在写。

直接上代码:
endListDialog.h

#ifndef ENDLISTDIALOG_H
#define ENDLISTDIALOG_H#include <QDialog>
#include <QDebug>
namespace Ui {
class endListDialog;
}class endListDialog : public QDialog
{Q_OBJECTpublic:explicit endListDialog(QWidget *parent = nullptr);~endListDialog();private slots:void onHoverTimeout();
protected:void mouseMoveEvent(QMouseEvent *event);void switchPage(int index);
private:Ui::endListDialog *ui;bool isHovering;QTimer *timer;
};#endif // ENDLISTDIALOG_H

endListDialog.cpp

#include "endlistdialog.h"
#include "ui_endlistdialog.h"
#include <QTimer>
#include <QMouseEvent>
#include <QMessageBox>
#include <QPropertyAnimation>
bool bshow=false;//鼠标事件mouseMoveEvent必须按下才响应 为了实现将页面所有QWidget setMouseTracking属性赋值true
void setMouseTrackingRecursively(QWidget* widget) {if (widget == nullptr)return;widget->setMouseTracking(true);const QObjectList& children = widget->children();for (QObject* child : children) {if (child->isWidgetType()) {setMouseTrackingRecursively(qobject_cast<QWidget*>(child));}}
}//同理QWidget 透明设置
void setwindowOpacityRecursively(QWidget* widget) {if (widget == nullptr)return;widget->setMouseTracking(true);const QObjectList& children = widget->children();for (QObject* child : children) {if (child->isWidgetType()) {setwindowOpacityRecursively(qobject_cast<QWidget*>(child));}}
}/****************************/
//切换页面实现
//入参 index 页面 (这里偷懒直接写了固定的实现)
//输出 
/****************************/
void endListDialog::switchPage(int index)
{//我的ui QStackedWidget对象是stackedWidget_18,换成自己的QWidget *currentWidget = ui->stackedWidget_18->currentWidget();QWidget *nextWidget = ui->stackedWidget_18->widget(index);// 创建动画// 创建缩小动画QPropertyAnimation *fadeOutAnimation = new QPropertyAnimation(currentWidget, "geometry");fadeOutAnimation->setDuration(200);QRect originalGeometry = currentWidget->geometry();QRect targetGeometry;if(index==1){ //展示第二页时 将第一页缩小一点 targetGeometry = QRect(originalGeometry.x() +20,originalGeometry.y() ,originalGeometry.width()-40,originalGeometry.height());}else{//展示第一页时 将第二页放大一点 targetGeometry = QRect(originalGeometry.x() -20,originalGeometry.y() ,originalGeometry.width()+40,originalGeometry.height());}fadeOutAnimation->setStartValue(originalGeometry);fadeOutAnimation->setEndValue(targetGeometry);QPropertyAnimation *fadeInAnimation = new QPropertyAnimation(nextWidget, "windowOpacity");fadeInAnimation->setDuration(600);fadeInAnimation->setStartValue(0.0);fadeInAnimation->setEndValue(1.0);// 连接动画完成信号connect(fadeOutAnimation, &QPropertyAnimation::finished, this, [this, index]() {ui->stackedWidget_18->setCurrentIndex(index);});// 启动动画fadeOutAnimation->start();fadeInAnimation->start();
}endListDialog::endListDialog(QWidget *parent) :QDialog(parent),ui(new Ui::endListDialog)
{ui->setupUi(this);isHovering = false;timer = new QTimer();timer->setInterval(200); // 设置为 600 m秒connect(timer, &QTimer::timeout, this, &endListDialog::onHoverTimeout);setMouseTrackingRecursively(ui->widget);setwindowOpacityRecursively(ui->widget);
}endListDialog::~endListDialog()
{delete ui;
}//mouseMoveEvent的重写 ,千万记住setMouseTracking属性赋值true
//不然你只能按住才能触发 Qt为了缩减资源消耗默认赋值false
void endListDialog::mouseMoveEvent(QMouseEvent *event) {// 检查鼠标是否在 stackedWidget 内if (ui->stackedWidget_18->underMouse()) {// 鼠标在 stackedWidget 内部qDebug("Mouse is inside the stackedWidget");if (!isHovering) { // 仅在未悬浮时启动计时器isHovering = true;bshow=false;timer->start();}} else {// 鼠标不在 stackedWidget 内部qDebug("Mouse is outside the stackedWidget");if (isHovering) { // 仅在悬浮时停止计时器isHovering = false;timer->stop();switchPage(0);}}// 调用基类的 mouseMoveEventQDialog::mouseMoveEvent(event);
}void endListDialog::onHoverTimeout() {// 在这里执行悬浮超过3秒后的操作// 例如,显示提示信息// QMessageBox::information(this, "提示", "鼠标悬浮超过3秒!");if(!bshow){switchPage(1);bshow = true;}
}
http://www.lryc.cn/news/546711.html

相关文章:

  • 数据结构第五节:排序
  • 从文件到块: 提高 Hugging Face 存储效率
  • Android14 串口控制是能wifi adb实现简介
  • vue3中 组合式~测试深入组件:事件 与 $emit()
  • SQL-labs13-16闯关记录
  • 基于微信小程序的停车场管理系统的设计与实现
  • DAIR-V2X-R数据集服务器下载
  • table 拖拽移动
  • Linux使用笔记:Find Tree 命令
  • 数据结构入门篇——什么是数据结构。
  • MySQL-简介与基本命令
  • 汽车材料耐候性测试仪器-太阳光模拟器介绍
  • 音频3A测试--AEC(回声消除)测试
  • DeepSeek 助力 Vue3 开发:打造丝滑的弹性布局(Flexbox)
  • 六、Redis 高级功能详解:BitMap、HyperLogLog、Geo、Stream
  • WSL下使用git克隆失败解决
  • 【Elasticsearch】索引生命周期管理相关的操作(Index Lifecycle Actions)
  • TS的接口 泛型 自定义类型 在接口中定义一个非必须的属性
  • Collab-Overcooked:专注于多智能体协作的语言模型基准测试平台
  • 未来经济范式争夺战:AR眼镜为何成为下一代交互终端的制高点?
  • Mybatis实现批量添加
  • golang 内存对齐和填充规则
  • 【YashanDB认证】yashandb23.3.1 个人版单机部署安装实践
  • 安全渗透测试的全面解析与实践
  • 通俗易懂的分类算法之决策树详解
  • 【OpenCV C++】以时间命名存图,自动检查存储目录,若不存在自动创建, 按下空格、回车、Q、S自动存图
  • post get 给后端传参数
  • 数据仓库的特点
  • 任务9:交换机基础及配置
  • ArcGIS操作:07 绘制矢量shp面