项目开发,想实现动态的显示按钮,考虑使用QStackedWidget做两个页面去切换。
首先,我们使用Qt ui 画出两个QStackedWidget的两个页面
要实现切换,我们只需要调用stackedWidget->setCurrentIndex(index)
就行。
那么如何自动调用呢?
这时候,我们想到网页的正常操作。当鼠标在某个区悬浮超过固定时间时,将按钮显示出来,也就是切换页面。
这里我们遇到了个坑, Qt为了缩减资源消耗,只在鼠标按下才触发
mouseMoveEvent!
切记修改MouseTracking属性,我们修改了整个ui的MouseTracking属性发现没有用???
查资料,需要将所有QWidget子节点全部赋值!
cpp
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
cpp
#ifndef ENDLISTDIALOG_H
#define ENDLISTDIALOG_H
#include <QDialog>
#include <QDebug>
namespace Ui {
class endListDialog;
}
class endListDialog : public QDialog
{
Q_OBJECT
public:
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
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);
}
}
// 调用基类的 mouseMoveEvent
QDialog::mouseMoveEvent(event);
}
void endListDialog::onHoverTimeout() {
// 在这里执行悬浮超过3秒后的操作
// 例如,显示提示信息
// QMessageBox::information(this, "提示", "鼠标悬浮超过3秒!");
if(!bshow)
{
switchPage(1);
bshow = true;
}
}