【三十四】【QT开发应用】音量图标以及滑动条,没有代码补全的小技巧
效果展示
- 鼠标位于音量图标区域内,显示出滑动条。鼠标移出音量图标区域内滑动条隐藏。
- 鼠标点击音量图标,如果此时音量为0,音量变成50,如果此时音量不为零,音量变为0。
CVolumeButton.h 音量图标头文件
#pragma once
#include <QtWidgets>
#include "CVolumeSliderDialog.h"class CVolumeButton :public QPushButton {Q_OBJECT
public:CVolumeButton(QWidget* p = nullptr);~CVolumeButton();protected:void enterEvent(QEnterEvent* event) override;void timerEvent(QTimerEvent* event) override;void mousePressEvent(QMouseEvent* event) override;private:CVolumeSliderDialog* m_pVolumeSliderDlg = nullptr;int m_timerId = -1;bool m_isMute = false;
};
#include <QtWidgets>
是 Qt 库中用于引入所有与图形用户界面(GUI)相关控件的头文件。可以理解为是一个模块头文件,用这一个头文件就可以包含许多其他的头文件,和C++中的万能头文件#include<bits/stdc++>
有异曲同工之妙。通过#include <QtWidgets>
,你可以一次性引入所有常用的 GUI 控件,而无需单独引入每个控件的头文件。它包含了大部分用于创建桌面应用程序的常见控件,比如 QMainWindow、QDialog、QPushButton 等。- 重载了这三个函数事件,
enterEvent
是进入事件,也就是说当鼠标进入到空间区域内会触发的事件.timerEvent
是定时器事件,设置完毕定时器之后,每过一段事件就会触发一遍定时器内的函数逻辑.mousePressEvent
是鼠标按下事件,当鼠标按下按键之后,会触发的事件.void enterEvent(QEnterEvent* event) override;void timerEvent(QTimerEvent* event) override;void mousePressEvent(QMouseEvent* event) override;
CVolumeSliderDialog
是滑动条类,m_timerId
是定时器的ID,创建出一个定时器之后会返回一个定时器ID,m_isMute
用来判断音量是否不为0,也就是说判断是否有音量.CVolumeSliderDialog* m_pVolumeSliderDlg = nullptr;int m_timerId = -1;bool m_isMute = false;
CVolumeButton.cpp 音量图标源文件
#include "CVolumeButton.h"CVolumeButton::CVolumeButton(QWidget* p):QPushButton(p) {this->setFixedSize(32, 32);setStyleSheet(R"(
QPushButton{
background-image:url(:/widget/resources/audio_open.svg);
border:none;
}
QPushButton:hover{
background-image:url(:/widget/resources/audio_open_hover.svg);
}
QPushButton:pressed{
background-image:url(:/widget/resources/audio_open.svg);
}
)");}CVolumeButton::~CVolumeButton() {}void CVolumeButton::enterEvent(QEnterEvent* event) {qDebug() << "1111111";if (m_pVolumeSliderDlg == nullptr) m_pVolumeSliderDlg = new CVolumeSliderDialog(this);QPoint p1 = this->mapToGlobal(QPoint(0, 0));//局部坐标(0, 0)转换为全局坐标p1QRect rect1 = this->rect();//获取当前按钮的矩形区域QRect rect2 = m_pVolumeSliderDlg->rect();//获取滑动条的矩形区域int x = p1.x() + (rect1.width() - rect2.width()) / 2;int y = p1.y() - rect2.height();m_pVolumeSliderDlg->move(x, y);//将滑动条移动到(x,y)位置,全局坐标(x,y)m_pVolumeSliderDlg->show();//显示滑动条m_timerId = startTimer(250);//启动定时器,返回定时器ID,定时器间隔250ms触发一次
}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->geometry();//获取全局矩形区域QPoint p2 = this->mapToGlobal(QPoint(0, 0));QRect arec(rect2.left(), rect2.top(), rect2.width(), p2.y() + rect1.height() - rect2.top());//定义滑动条显示的情况下鼠标存在的区域if (!arec.contains(p1))//如果arec不包含p1,隐藏滑动条m_pVolumeSliderDlg->hide();}}
}void CVolumeButton::mousePressEvent(QMouseEvent* event) {if (m_pVolumeSliderDlg->isZeroValue()) {//判断滑动条值是否为0m_isMute = false;//为零表示不存在音量值} else {m_isMute = true;//否则表示存在音量值}if (event->button() == Qt::LeftButton) {//如果左键点击按钮if (m_isMute) {//如果有音量if (m_pVolumeSliderDlg) {m_pVolumeSliderDlg->setSliderValue(0);//音量置0}} else {if (m_pVolumeSliderDlg) {m_pVolumeSliderDlg->setSliderValue(50);//否则置50}}}
}
enterEvent
进入事件,当鼠标进入到音量图标控件区域内就会触发的事件函数.
我们希望触发的事件是显示出滑动条,并且滑动条显示的位置在音量控件的正上方,水平居中对齐.因此我们需要设置滑动条的位置,通过使用move(x,y)函数操作使滑动条移动到指定的位置.
timerEvent
定时器事件,设置定时器时间,定时器会每间隔time时间就运行一遍函数.
rect和geometry的区别
rect()
- 返回值:控件自身的局部坐标系中的矩形区域,仅代表控件本身的尺寸(宽度和高度),而不包含控件相对于屏幕或父窗口的位置。
x()
和y()
均为 0,因为这个矩形是以控件的左上角为原点的局部坐标。width()
和height()
分别表示控件的宽度和高度。- 使用场景:当你只关心控件的尺寸(宽度和高度),而不关心它相对于父控件或屏幕的位置时,使用
rect()
。
geometry()
- 返回值:控件在父控件或屏幕上的绝对矩形区域,即控件的相对位置(x 和 y 坐标)以及它的尺寸(宽度和高度)。
x()
和y()
表示控件相对于父控件或窗口的左上角位置。width()
和height()
与rect()
返回的尺寸相同,表示控件的宽度和高度。- 使用场景:当你需要知道控件在父控件或屏幕中的具体位置(包括坐标和尺寸)时,使用
geometry()
。
区别总结:
rect()
:只提供控件的宽度和高度,左上角坐标总是 (0, 0)。geometry()
:不仅提供控件的宽度和高度,还包含控件相对于父控件或屏幕的左上角位置坐标 (x, y)。
- 局部坐标转化为全局坐标
QPoint p1 = this->mapToGlobal(QPoint(0, 0));
- 设置控件左上角坐标
m_pVolumeSliderDlg->move(x, y);
- 获取鼠标全局坐标
QPoint p1 = QCursor::pos();
CVolumeSliderDialog.h 滑动条头文件
#pragma once
#include <QtWidgets>class CVolumeSliderDialog :public QWidget {Q_OBJECT
public:CVolumeSliderDialog(QWidget* p = nullptr);~CVolumeSliderDialog();void setSliderValue(int value) {m_pSlider->setValue(value);}bool isZeroValue() {return m_pSlider->value() == 0;}private:QSlider* m_pSlider = nullptr;
};
setSliderValue
函数内置控制滑动条的函数,我们可以通过QSlider
直接控制滑动条的值,为啥还需要内置一个函数去控制?因为我们运用CVolumeSliderDialog
类无法控制私有的变量,所以需要共有的函数去控制isZeroValue
函数内置判断滑动条值是否为0.
CVolumeSliderDialog.cpp
#include "CVolumeSliderDialog.h"CVolumeSliderDialog::CVolumeSliderDialog(QWidget* p):QWidget(p) {this->setFixedSize(40, 120);QVBoxLayout* pVLay = new QVBoxLayout(this);m_pSlider = new QSlider(this);m_pSlider->setOrientation(Qt::Vertical);pVLay->addWidget(m_pSlider);setStyleSheet(R"(
QDialog{
background-color:rgba(54,54,54,0.5);
}
)");setWindowFlags(Qt::ToolTip);}
CVolumeSliderDialog::~CVolumeSliderDialog() {}
-
setWindowFlags(Qt::ToolTip);
这是一个 WindowType 标志,表示窗口将被设置为类似工具提示(ToolTip)的窗口。- 特点
- 没有标题栏,也不会显示在任务栏或窗口列表中。
- 无法通过点击或拖动对其进行交互。
- 通常用于显示一些临时性的信息,比如提示文本、悬停提示等。
- 特点
-
m_pSlider->setOrientation(Qt::Vertical);
这行代码用于将滑块控件 (QSlider 或类似的控件) 的方向设置为垂直方向 (Qt::Vertical)。
widget.cpp
#include "widget.h"
#include "QtWidgets"
#include "CVolumeButton.h"
#include "CVolumeSliderDialog.h"widget::widget(QWidget* parent): QWidget(parent) {ui.setupUi(this);resize(800, 600);QHBoxLayout* pHLay = new QHBoxLayout(this);CVolumeButton* pVolumeButton = new CVolumeButton(this);//CVolumeSliderDialog* ptemp = new CVolumeSliderDialog(this);pHLay->addWidget(pVolumeButton);}widget::~widget() {}
没有代码提示怎么办?
当你发现某一个关键字没有代码提示的时候,Ctrl+左键进入到目标文件中.
以QHBoxLayout关键字为例,进入之后复制文件夹的完整路径.
点开番茄助手添加复制的完整路径点击确定.
然后启动窗口,重新启动该程序,再次输入就会有代码补全了.
结尾
最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。
同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。
谢谢您的支持,期待与您在下一篇文章中再次相遇!