事件监听
事件监听(Event Handling)是在程序中监视和响应发生的事件的一种机制。在Qt中,事件监听是一种常见的用于处理用户输入、系统事件以及其他类型事件的方法。通过事件监听,您可以在发生特定事件时捕获事件并执行相应的操作,而无需手动轮询或定期检查事件的状态。
在Qt中,事件监听可以通过以下几种方式实现:
-
重写事件处理函数: 可以重写 Qt 对象的事件处理函数,例如
QWidget
、QMainWindow
等的事件处理函数,以处理特定类型的事件。例如,QWidget
有一个名为event()
的虚函数,允许您处理各种类型的事件,包括键盘事件、鼠标事件、绘图事件等。 -
安装事件过滤器: 可以为一个对象安装事件过滤器,从而拦截并处理该对象接收到的所有事件。通过重写事件过滤器的
eventFilter()
函数,您可以对特定类型的事件进行处理。事件过滤器允许您在一个地方集中处理多个对象的事件,而不必修改每个对象的代码。
事件监听的作用包括但不限于:
- 用户交互: 通过监听用户的鼠标点击、键盘输入等事件,可以实现用户界面的交互功能,例如按钮点击、文本输入、拖放操作等。
- 状态更新: 监听特定的系统或对象状态变化事件,可以及时更新应用程序的状态,例如窗口大小变化、文件加载完成等。
- 自定义行为: 通过捕获和处理特定的事件,可以实现应用程序的自定义行为和交互逻辑,例如拦截并处理特定的键盘快捷键、过滤用户输入等。
- 错误处理: 可以通过监听并处理异常、错误等事件,实现应用程序的错误处理和异常恢复机制。
总之,事件监听是 Qt 中实现用户交互、状态更新、自定义行为和错误处理等功能的重要机制,它使得开发者能够更加灵活和高效地处理各种类型的事件。
例
在前述预览窗口中指定需要显示的序列图像,使用eventFilter()重载对预览窗口的QLabel的MouseButtonRelease()Event做出对应的反应,包括:
- 将主窗口要显示的图像索引设置为当前QLabel的索引
- 解除前一个QLabel的选中状态,将当前QLabel设置为选中状态
为QLabel和scrollableWidget设置事件监听
ScrollableWidget* scrollableWidget = new ScrollableWidget(l_num);
scrollableWidget->installEventFilter(scrollableWidget);
label->installEventFilter(this);
eventFilter重载
private:
vector<QLabel*> PreWinLst;
vector<QWidget*> PreWinLst_Wid;
int Current_mainWin_Srs_Idx = 0;
//此时QLabel指向ScrollableWidget的子控件,
//子控件直接随着ScrollableWidget析构释放了,不需要额外释放QLabel指针指向的内存
//PreWinLst内部管理的内存由vector析构函数释放
public:
bool eventFilter(QObject* obj, QEvent* event) override {
for (int i = 0; i < PreWinLst.size(); i++)
{
if (obj == PreWinLst[i] && event->type() == QEvent::MouseButtonRelease)
{
PreWinLst[Current_mainWin_Srs_Idx]->setStyleSheet("border-color: rgb(255, 255, 255);");
Current_mainWin_Srs_Idx = i;
PreWinLst[Current_mainWin_Srs_Idx]->setStyleSheet("border-style: solid;border-width: 5px;border-color: rgb(10, 100, 160);");
return true;
}
}
return false;
}
代码及结果
#pragma once
#include <QtWidgets/QMainWindow>
#include <QtWidgets>
#include "ui_dcmimgpro.h"
using namespace std;
class DcmImgPro : public QMainWindow
{
Q_OBJECT
public:
DcmImgPro(QWidget *parent = nullptr);
~DcmImgPro();
private:
Ui::DcmImgProClass ui;
private slots:
void pushbtn();
void lineEditset();
private:
int l_num = 15;
};
class ScrollableWidget:public QWidget
{
public:
ScrollableWidget(int numWidgets)
{
QVBoxLayout* layout = new QVBoxLayout(this);
for (int i = 0; i < numWidgets; i++)
{
QWidget* widget = new QWidget;
widget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
widget->setMinimumSize(QSize(200, 200));
QLabel* label = new QLabel;
label->setGeometry(QRect(0, 0, widget->width(), widget->height()));//全屏铺满
label->setMinimumSize(QSize(180, 180));
label->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
// 创建一个渐变对象,并设置渐变色
QLinearGradient gradient(0, 0, 200, 200); // 从左到右的线性渐变
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(0.5, Qt::green);
gradient.setColorAt(1, Qt::blue);
// 创建一个QPixmap,并使用渐变填充
QPixmap pixmap(200, 200);
pixmap.fill(Qt::transparent); // 填充透明背景
QPainter painter(&pixmap);
painter.fillRect(pixmap.rect(), gradient);
label->setPixmap(pixmap);
label->installEventFilter(this);
QVBoxLayout* widgetlayout = new QVBoxLayout(widget);
widgetlayout->addWidget(label);
layout->addWidget(widget);
PreWinLst.push_back(label);
PreWinLst_Wid.push_back(widget);
}
}
bool eventFilter(QObject* obj, QEvent* event) override {
for (int i = 0; i < PreWinLst.size(); i++)
{
if (obj == PreWinLst[i] && event->type() == QEvent::MouseButtonRelease)
{
PreWinLst[Current_mainWin_Srs_Idx]->setStyleSheet("border-color: rgb(255, 255, 255);");
Current_mainWin_Srs_Idx = i;
PreWinLst[Current_mainWin_Srs_Idx]->setStyleSheet("border-style: solid;border-width: 5px;border-color: rgb(10, 100, 160);");
return true;
}
}
return false;
}
private:
vector<QLabel*> PreWinLst;
vector<QWidget*> PreWinLst_Wid;
int Current_mainWin_Srs_Idx = 0;
//此时QLabel指向ScrollableWidget的子控件,
//子控件直接随着ScrollableWidget析构释放了,不需要额外释放QLabel指针指向的内存
//PreWinLst内部管理的内存由vector析构函数释放
};
#include "dcmimgpro.h"
DcmImgPro::DcmImgPro(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
ui.scrollArea->setWidgetResizable(true);
ScrollableWidget* scrollableWidget = new ScrollableWidget(l_num);
scrollableWidget->installEventFilter(scrollableWidget);
ui.scrollArea->setWidget(scrollableWidget);
ui.lineEdit->setText(QString::number(l_num));
connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(pushbtn()));
connect(ui.lineEdit, SIGNAL(editingFinished()), this, SLOT(lineEditset()));
//textChanged cursorPositionChanged
//editingFinished selectionChanged returnPressed()
}
void DcmImgPro::pushbtn()
{
ui.scrollArea->setWidget(nullptr);
ScrollableWidget* scrollableWidget = new ScrollableWidget(l_num);
ui.scrollArea->setWidget(scrollableWidget);
}
void DcmImgPro::lineEditset()
{
l_num = ui.lineEdit->text().toInt();
}
DcmImgPro::~DcmImgPro()
{
}
ChatGPT生成的代码解析
这段代码定义了两个类:DcmImgPro
和 ScrollableWidget
。
-
DcmImgPro 类:
-
DcmImgPro
类是一个继承自 QMainWindow 的类,它具有一个构造函数和一个析构函数。构造函数中使用了一个名为ui
的私有成员对象,该对象是通过 UI 设计工具(如 Qt Designer)生成的界面类的实例。构造函数还初始化了一个名为l_num
的私有成员变量,并赋值为 15。 - 类中声明了两个私有槽函数
pushbtn()
和lineEditset()
,这些槽函数可以与界面中的按钮、文本框等控件的信号关联起来,以实现对应的功能。
-
-
ScrollableWidget 类:
-
ScrollableWidget
类是一个自定义的 QWidget 子类,用于创建可滚动的窗口。它接受一个整数参数numWidgets
,用于指定需要创建的子控件(QLabel)的数量。 - 在构造函数中,使用循环创建了指定数量的 QWidget 和 QLabel 控件,并将它们添加到垂直布局中。每个 QLabel 控件都包含一个渐变的 QPixmap,用于填充其背景。此外,每个 QLabel 控件还安装了事件过滤器,以便捕获鼠标释放事件。
- 在事件过滤器中,当捕获到鼠标释放事件时,首先清除当前被选中 QLabel 的边框颜色,然后更新当前被选中 QLabel 的索引,并为其设置新的边框样式。
-
总的来说,DcmImgPro
类是一个主窗口类,用于创建应用程序的主界面,并处理界面上的按钮点击等事件;ScrollableWidget
类是一个自定义的可滚动窗口部件,用于创建一个包含多个 QLabel 的可滚动区域,每个 QLabel 带有渐变背景和边框样式,并可以捕获鼠标释放事件以实现选中效果。
其中ScrollableWidget
类是一个自定义的 QWidget 子类,它的主要功能是创建一个可滚动的窗口,并在其中放置多个带有渐变背景的 QLabel 控件。下面是对 ScrollableWidget
类的详细解释:
-
构造函数:
-
ScrollableWidget
类的构造函数接受一个整数参数numWidgets
,用于指定要创建的子控件(QLabel)的数量。 - 在构造函数中,首先创建了一个垂直布局管理器
QVBoxLayout
,并将其设置为ScrollableWidget
的布局管理器,以便放置子控件。 - 然后使用一个循环,根据参数
numWidgets
的值,创建了指定数量的 QWidget 和 QLabel 控件,并将它们添加到垂直布局中。
-
-
创建子控件:
- 在循环中,首先创建了一个 QWidget 控件,用于容纳一个 QLabel 控件。
- 对每个 QWidget 控件进行了一些设置,包括设置其大小策略为固定大小,并设置其最小大小为 (200, 200) 像素。
- 然后创建了一个 QLabel 控件,并设置了它的对齐方式为居中对齐。
-
设置渐变背景:
- 在每个 QLabel 控件中,使用
QLinearGradient
创建了一个线性渐变对象,并设置了渐变的起始和结束颜色。 - 创建一个与 QLabel 控件相同大小的 QPixmap,并使用渐变对象填充该 QPixmap。
- 最后,将该 QPixmap 设置为 QLabel 控件的背景。
- 在每个 QLabel 控件中,使用
-
安装事件过滤器:
- 对每个 QLabel 控件调用了
installEventFilter(this)
,将ScrollableWidget
自身作为事件过滤器。这意味着ScrollableWidget
类会监听每个 QLabel 控件的事件。
- 对每个 QLabel 控件调用了
-
事件过滤器:
- 重写了
eventFilter
函数,在该函数中捕获了鼠标释放事件。 - 当鼠标释放事件发生时,首先清除了当前被选中 QLabel 控件的边框颜色,然后更新了当前被选中 QLabel 控件的索引,并为其设置了新的边框样式。
- 重写了
总的来说,ScrollableWidget
类是一个用于创建带有渐变背景的可滚动窗口部件,其中包含多个 QLabel 控件。它允许用户点击任意 QLabel 控件,并在其周围绘制一个特定样式的边框以指示选中状态。