赞
踩
往期回顾:
【QT入门】 Qt自定义控件与样式设计之qss选择器-CSDN博客
鼠标悬浮弹出对话框的功能:最终要实现纯代码设计出一个音量按钮,当鼠标悬浮在上面的时候,显示滑块,并可以自己调节大小,鼠标离开后滑块消失。
首先实现一个基本功能,就是窗口能识别鼠标,鼠标放上去就显示,不放上去就不显示,这个功能很简单只需要重写两个函数
void enterEvent(QEvent * event) override;
void leaveEvent(QEvent * event) override;
在Widget主窗口写这两个类,你那么就能实现鼠标放进主窗口有反应,拿出来也有反应
- void Widget::enterEvent(QEvent * event)
- {
- qDebug()<<"11111";
- }
-
- void Widget::leaveEvent(QEvent * event)
- {
- qDebug()<<"22222";
- }
Widget类加载主布局,主类没操作,就是设置大小,创建布局,把按钮放进去。
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
-
- resize(800, 600);
-
- //创建水平布局
- QHBoxLayout *pHlay = new QHBoxLayout(this);
-
- //创建音量按钮并添加到布局水平布局里
- CVolumeButton* pVolumeButton = new CVolumeButton(this);
- pHlay->addWidget(pVolumeButton);
- }
这个类本身继承自QDialog,主要作用是创建QSlider对象并添加到布局中。
QSlider是用于控制边界值的经典小部件。它允许用户沿水平或垂直凹槽移动QSlider 的滑块,并将 滑块 的位置转换为合法范围内的整数值。
- //设置对话框的固定大小为(40, 200)
- this->setFixedSize(40, 200);
-
- //创建一个垂直布局管理器pVLay,
- QVBoxLayout* pVLay = new QVBoxLayout(this);
- m_pSlider = new QSlider(this);
-
- //将一个垂直方向的QSlider对象m_pSlider添加到布局中
- m_pSlider->setOrientation(Qt::Vertical);
- pVLay->addWidget(m_pSlider);
另外比较重要的一点,把设置窗口标志为无边框窗口和ToolTip提示框样式
这里用到一个ToolTip,ToolTip = Popup | Sheet ,可以实现滑块悬浮时显示,离开时消失
- setFixedSize(40, 120);
- //设置窗口标志为无边框窗口和ToolTip提示框样式
- //ToolTip = Popup | Sheet,
- setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); //ToolTip : 悬浮时显示,离开时消失
- setStyleSheet("QDialog{background-color: rgba(54, 54, 54, 0.5);}"); //0.5表示透明度,0表示全透明、1表示不透明;
- //也可以使用百分百表示如: frm->setStyleSheet(“QFrame{background-color: rgba(255, 0, 0, 50%);}”);
bug: bool QWidget::event(QEvent *event)这个方法设置popup后,dialog会有窗口阴影
需要去除就重写event函数,
- bool CVolumeSliderDialog::event(QEvent* event)
- {
- //定义一个静态布尔变量class_amended,用于跟踪是否已经修改了窗口类。
- static bool class_amended = false;
-
- //事件类型为WinIdChange,表示窗口标识已更改。
- if (event->type() == QEvent::WinIdChange)
- {
- //获取对话框的窗口句柄
- HWND hwnd = (HWND)winId();
-
- //检查是否已经修改了窗口类
- if (class_amended == false)
- {
- class_amended = true;//将class_amended设置为true,表示已经修改了窗口类
- DWORD class_style = ::GetClassLong(hwnd, GCL_STYLE);//获取窗口类的样式
- //将CS_DROPSHADOW样式从窗口类样式中移除,这样可以去除窗口阴影
- class_style &= ~CS_DROPSHADOW;
- //将修改后的窗口类样式应用到窗口
- ::SetClassLong(hwnd, GCL_STYLE, class_style); // windows系统函数
- }
- }
-
- //调用基类QWidget的event函数来处理事件,确保其他事件得到正常处理
- return QWidget::event(event);
- }
注意这个完全可以作为一个通用类,需要的时候直接使用。
cvolumebutton类实现音量按钮的创建和滑块的绑定以及逻辑实现
主要是几个逻辑实现:
1、纯代码创建一个音量按钮 |
2、创建滑块并定位在按钮上方合适位置 |
3、判断是否点击按钮需要静音来改变滑块上的位置 |
4、通过定时器判断鼠标是否离开按钮和滑块区域,离开滑块就消失 |
- //代码可重用
- void CVolumeButton::paintEvent(QPaintEvent*)
- {
- //QStylePainter用于绘制基于QStyle的外观元素
- QStylePainter p(this);
-
- //QStyleOptionButton用于存储按钮控件的外观选项,如颜色、边框等
- QStyleOptionButton option;
-
- //调用initStyleOption方法初始化option对象
- //initStyleOption通常用于设置控件的外观选项,以便正确绘制控件
- initStyleOption(&option);
-
- //使用QStylePainter对象p绘制一个CE_PushButton类型的控件,参数为option对象。
- //这将根据option中的外观选项绘制按钮的外观,如背景、文本等
- p.drawControl(QStyle::CE_PushButton, option);
- }
- void CVolumeButton::enterEvent(QEvent* event)
- {
- //判断并初始化滑块对象,确保只有在需要时才创建滑块对象
- if (!m_pVolumeSliderDlg)
- m_pVolumeSliderDlg = new CVolumeSliderDialog(this);
-
-
- QPoint p1 = this->mapToGlobal(QPoint(0, 0)); //声音按钮左上角相对于桌面的绝对位置
- QRect rect1 = this->rect(); //获取声音按钮的矩形区域
- //获取滑块对象的矩形区域,rect包含标题栏,去掉标题栏后height不变
- QRect rect2 = m_pVolumeSliderDlg->rect();
-
- //计算滑块对象在水平方向上的位置,使其水平居中于声音按钮
- //这里计算很简单,就是按钮的一半减去滑块的一半,就是多出来的那部分
- //按钮的x加上多出来那部分,就能得到滑块居中的x位置
- int x = p1.x() + (rect1.width() - rect2.width()) / 2;
-
- //计算滑块对象在垂直方向上的位置,使其位于声音按钮上方并略微偏移5px
- //按钮的y减去滑块的长度再减去偏移的5px,就是滑块的左上角y位置
- int y = p1.y() - rect2.height() - 5;
- //滑块对象移动到计算得到的位置
- m_pVolumeSliderDlg->move(x, y); //move是相对于桌面原点的位置
-
- m_pVolumeSliderDlg->show();//显示滑块对象
- m_timerId = startTimer(250);//动一个定时器,每250毫秒触发一次定时器事件
-
- connect(m_pVolumeSliderDlg, &CVolumeSliderDialog::sig_SliderValueChanged, [=](int value) {
- emit sig_VolumeValue(value);
- });
- }
- void CVolumeButton::mousePressEvent(QMouseEvent* event)
- {
- if (event->button() == Qt::LeftButton)//检查鼠标按下的按钮是否是左键
- {
- m_isMute = !m_isMute; //切换静音状态,真假切换
- if (m_isMute)//如果当前为静音状态
- {
- //如果滑块对象存在,将滑块值设置为0,表示静音状态
- if (m_pVolumeSliderDlg)
- m_pVolumeSliderDlg->setSliderValue(0);
- }
- else
- {
- //如果滑块对象存在,将滑块值设置为50,表示非静音状态下的默认音量
- if (m_pVolumeSliderDlg)
- m_pVolumeSliderDlg->setSliderValue(50);
- }
- }
- }
- void CVolumeButton::timerEvent(QTimerEvent* event)
- {
- //检查音量滑块对象是否存在且可见
- if ((m_pVolumeSliderDlg != nullptr) && (m_pVolumeSliderDlg->isVisible()))
- {
- QPoint p1 = QCursor::pos(); //鼠标绝对位置
- if (m_pVolumeSliderDlg)
- {
- QRect rect1 = this->rect(); //获取声音按钮的矩形区域
- QRect rect2 = m_pVolumeSliderDlg->rect();//获取音量滑块对象的矩形区域
- QRect rect3 = m_pVolumeSliderDlg->geometry();//获取音量滑块对象的几何信息
-
- QPoint p2 = this->mapToGlobal(QPoint(0, 0)); //声音按钮左上角相对于桌面的绝对位置
-
- //已知:音量框宽40 > 按钮宽30
- //创建一个矩形区域,用于检测鼠标位置是否在音量滑块对象或声音按钮上
- QRect area(rect3.left(), rect3.top(), rect2.width(), p2.y() + rect1.height() - rect3.top()); //左上宽高
-
- if (!area.contains(p1))//如果鼠标位置不在矩形区域内
- {
- m_pVolumeSliderDlg->hide();//隐藏音量滑块对象
- }
- }
- }
- else //如果鼠标位置在矩形区域内
- {
- //停止定时器,即终止定时器事件的触发
- killTimer(m_timerId);
- }
- }
都看到这里了,点个赞再走呗朋友~
加油吧,预祝大家变得更强!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。