Qt基础006(事件)
文章目录
- 消息对话框QMessageBox
- 快捷键开发基础
- 事件
- 事件处理过程
- 事件过滤器
消息对话框QMessageBox
QMessageBox 是 Qt 框架中用于显示消息框的一个类,它常用于向用户显示信息、询问问题或者报告错
误。以下是 QMessageBox 的一些主要用途:
- 显示信息:向用户显示一些信息性的消息。
- 询问用户决策:询问用户一个问题,并根据其回答做出相应的操作。
- 报告错误:向用户报告程序运行中的错误。
代码示例
以下是一个简单的 QMessageBox 使用示例,展示了如何创建一个基本的消息框:
#include <QApplication>
#include <QMessageBox>
int main(int argc, char *argv[]) {QApplication app(argc, argv);QMessageBox msgBox;msgBox.setWindowTitle("Message Title");msgBox.setText("This is the main message text.");msgBox.setInformativeText("This is additional informative text.");msgBox.setIcon(QMessageBox::Information);msgBox.addButton(QMessageBox::Ok);msgBox.addButton(QMessageBox::Cancel);msgBox.setDefaultButton(QMessageBox::Ok);int ret = msgBox.exec();if (ret == QMessageBox::Ok) {// 用户点击了 OK} else if (ret == QMessageBox::Cancel) {// 用户点击了 Cancel}return app.exec();
}
在这个例子中,我们创建了一个 QMessageBox 对象,并设置了窗口标题、主要文本、附加信息文本和图标。还添加了两个按钮(OK 和 Cancel),并设置了默认按钮。通过 exec() 方法显示消息框,并根据用户的选择执行不同的操作。由于 QMessageBox 是为标准对话框设计的,其定制能力有限,但你可以通过添加自定义按钮来实现一定程度的定制。例如,如果你想要添加一个自定义的按钮,可以这样做:
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
int main(int argc, char *argv[]) {QApplication app(argc, argv);QMessageBox msgBox;msgBox.setText("Custom message box with a custom button");QPushButton *customButton = msgBox.addButton("自定义的名字",QMessageBox::ActionRole);msgBox.exec();if (msgBox.clickedButton() == customButton) {// 用户点击了自定义按钮}return app.exec();
}
在这个例子中,通过 addButton() 方法添加了一个自定义按钮。按钮的角色被设置为QMessageBox::ActionRole
,这意味着它将被放置在对话框的底部,与其他标准按钮一起。通过检查用户点击的按钮来确定是否点击了自定义按钮。
快捷键开发基础
在 Qt 中实现快捷键功能通常涉及到 QShortcut
类的使用。下面是一个简单的代码示例,展示了如何在Qt 应用程序中为特定功能设置快捷键:
// 创建一个快捷键 (Ctrl + N) 并关联到窗口
QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+N"), &window);
// 当快捷键被按下时,显示一个消息框
QObject::connect(shortcut, &QShortcut::activated, [&]() {
QMessageBox::information(&window, "Shortcut Activated", "Ctrl+N was
pressed");
});
在这个示例中,当用户按下 Ctrl + N 时,程序将弹出一个消息框。这是通过创建一个 QShortcut 对象,并将其快捷键序列设置为 “Ctrl+N” 来实现的。然后,将 activated 信号连接到一个 Lambda 函数,该函数在快捷键被激活时执行。这种方法非常适用于为特定操作提供快速访问路径。
事件
事件处理过程
众所周知Qt是一个基于C++的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率才是最高的)。所以在Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会经过: 事件派发 -> 事件过滤->事件分发->事件处理 几个阶段。Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作,比如信号与槽就是一种
==事件(event)==是由系统或者 Qt 本身在不同的场景下发出的。当用户按下/移动鼠标、敲下键盘,或者是窗口关闭/大小发生变化/隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如鼠标/键盘事件等;另一些事件则是由系统自动发出,如计时器事件。每一个Qt应用程序都对应一个唯一的 QApplication 应用程序对象,然后调用这个对象的 exec() 函数,这样Qt框架内部的事件检测就开始了( 程序将进入事件循环来监听应用程序的事件 )。
int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow* w = new MainWindow;w.show();return a.exec();
}
事件在Qt中产生之后,的分发过程是这样的:
- 当事件产生之后,Qt使用用应用程序对象调用 notify() 函数将事件发送到指定的窗口:
[override virtual] bool QApplication::notify(QObject *receiver, QEvent *e);
- 事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤。
// 需要先给窗口安装过滤器, 该事件才会触发
[virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)
- 当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类:
[override virtual protected] bool QWidget::event(QEvent *event);
- 事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件。。。)分发给对应的事件处理器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函数),比如:鼠标事件:
// 鼠标按下
[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
// 鼠标释放
[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
// 鼠标移动
[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);
重写事件案例:
程序关闭之前的询问,鼠标进入,鼠标离开,窗口大小改变
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QMessageBox>
#include <QWheelEvent>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);}
Widget::~Widget()
{delete ui;
}
void Widget::enterEvent(QEvent *event)
{qDebug() << "mouse enter";
}
void Widget::leaveEvent(QEvent *event)
{qDebug() << "mouse leave";
}
void Widget::wheelEvent(QWheelEvent *event)
{qDebug() << event->angleDelta();
}
void Widget::closeEvent(QCloseEvent *event)
{int ret = QMessageBox::warning(this, tr("My Application"),tr("close the window\n""Do you want to close the window?"),QMessageBox::Ok | QMessageBox::No);switch(ret){case QMessageBox::Ok:event->accept();break;case QMessageBox::No:event->ignore();break;}
}
void Widget::resizeEvent(QResizeEvent *event)
{qDebug() << "oldSize:" << event->oldSize()<< "newSize:" << event->size();
}
void Widget::on_pushButton_clicked()
{
}
自定义按键
mybutton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QWidget>
class MyButton : public QWidget
{
Q_OBJECT
private:
QPixmap pic;
public:
explicit MyButton(QWidget *parent = nullptr);
protected:
void mousePressEvent(QMouseEvent *event) override;
void leaveEvent(QEvent *event) override;
void enterEvent(QEvent *event) override;
void paintEvent(QPaintEvent *event) override;
signals:
void clicked();
};
#endif //
mybutton.cpp
#include "mybutton.h"
#include <QPainter>
MyButton::MyButton(QWidget *parent) : QWidget(parent)
{pic.load(":/o1.png");setFixedSize(pic.size());update();
}
void MyButton::mousePressEvent(QMouseEvent *event)
{pic.load(":/o3.png");update();emit clicked();
}
void MyButton::leaveEvent(QEvent *event)
{pic.load(":/o1.png");update();
}
void MyButton::enterEvent(QEvent *event)
{pic.load(":/o2.png");update();
}
void MyButton::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.drawPixmap(rect(),pic);
}
事件过滤器
我们通过继承QTextEdit来重写事件实现Ctrl加滚轮的检测,还有一种处理方式,叫做事件过滤器
在Qt的事件处理过程中,引入事件过滤器(Event Filter)可以让你在事件达到目标对象之前进行拦截和处理。这是一种强大的机制,允许你在不同对象间共享事件处理逻辑或在父对象中集中处理特定事件。
下面是加入事件过滤器的步骤:
-
定义事件过滤器: 事件过滤器通常是一个重写了 QObject::eventFilter() 方法的对象。这个方法会在事件传递给目标对象之前被调用。
-
安装事件过滤器: 使用 QObject::installEventFilter() 方法安装事件过滤器。这个方法告诉Qt在将事件发送给特定对象之前先通过过滤器对象。例如,如果你想在父窗口中过滤子窗口的事件,你需要在父窗口的对象上调用 installEventFilter() ,并将子窗口作为参数传递。
-
事件过滤器逻辑: 在 eventFilter() 方法内部,你可以编写自定义逻辑来决定如何处理或忽略事件。如果此方法返回 true ,则表示事件已被处理,不应该继续传递;如果返回 false ,则事件将正常传递给目标对象。
-
事件分发: 当事件发生时,Qt首先将事件发送到安装了事件过滤器的对象。在这一步,eventFilter() 方法被调用。
-
决定是否传递事件: 根据 eventFilter() 方法的返回值,Qt决定是否继续向目标对象传递事件。如果过滤器返回 true ,事件处理到此结束;如果返回 false ,事件继续传递到原始目标对象。
-
目标对象处理事件: 如果事件过滤器允许事件继续传递,目标对象将像没有事件过滤器存在时那样处理事件。
事件过滤器特别适用于以下情况:
-
当你想在不修改子类代码的情况下改变事件的行为。
-
当多个对象需要共享相同的事件处理逻辑。
-
当你需要在更高的层级上监控或修改应用程序的事件流。
通过使用事件过滤器,Qt应用程序可以获得更大的灵活性和更细粒度的事件处理控制。