QT——记事本项目

1.给pushButton按键添加图片

1.1 首先复制存放图片的文件夹,打开Qt回到编辑页面,右键单击pro文件选择在Explorer中显示,将图片文件夹粘贴进去你的代码同目录即可

1.2 创建一个新的文件夹

1.3 点击Add Files,将所有图片添加进来,然后记得保存

1.4 如何给主窗口添加图片?进入ui界面,选中主窗体对象,右下方找到windowicon,点击选择资源添加图片即可。找到windowstitle可修改程序标题名称

1.5 右键单击pushButton选择样式表,点击添加资源,选中border-image即可为按键添加底图

2. 文件操作类QFile

cpp 复制代码
//==========================================================================
// 读取
//==========================================================================
void Widget::on_btnRead_clicked()
{
    // 1.打开文件
    QFile file("D:/QT/test.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "File open error";
        return; // 添加return以防止文件未打开时继续执行
    }

    // 2.读取文件信息
    QByteArray content = file.readAll();
    if (content.isEmpty()) {
        qDebug() << "File read error or empty file";
        file.close();
        return;
    }

    // 3.打印出文件中内容
    qDebug() << content.data();
    
    // 4.关闭文件
    file.close();
}

//==========================================================================
// 写入
//==========================================================================
void Widget::on_btnWrite_clicked()
{
    // 1.打开文件
    QFile file("D:/QT/test2.txt");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        qDebug() << "File open error";
        return;
    }

    // 2.向文件中写入内容
    QString data = "hello world! 我是米!";
    file.write(data.toUtf8());

    // 3.关闭文件
    file.close();
}

3. 文件操作类QTextStream

QTextStream是一个功能强大的类,用于处理文本数据,特别是在需要考虑字符编码和文本格式化情 况下。通过这些特性,它提供了一种灵活而强大的方式来读写和操作文本。

cpp 复制代码
//==========================================================================
// 读取
//==========================================================================
void Widget::on_btnstrRead_clicked() {
    // 1.打开文件
    QFile file("D:/QT/test.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "File open error";
        return; // 添加return以防止文件未打开时继续执行
    }

    QTextStream in(&file);
    in.setCodec("UTF-8");  // 设置编码为UTF-8
    // 2.读取整个文件的内容
    // QString context = in.read(file.size());
    // qDebug() << context;  // 输出整个文件内容

    // 3.按行读取文件内容
    while (!in.atEnd()) {
        QString line = in.readLine();
        qDebug() << line;           // 输出每一行的内容
        ui->textEdit->append(line); // 将文件中内容显示到textEdit中
    }
		// 4.关闭文件
    file.close();
}

//==========================================================================
// 写入
//==========================================================================
void Widget::on_btnstreamWrite_clicked() {
    // 1.打开文件
    QFile file("D:/QT/test.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "File open error";
        return; // 添加return以防止文件未打开时继续执行
    }

    // 2.向文件中写入内容
    QTextStream out(&file);
    out.setCodec("UTF-8");                 // 设置编码为UTF-8
    out << "I write stream char to File";  // 向文件写入文本
    
    // 3.关闭文件
    file.close();
}

4. 文件选择对话框 QFileDialog

4.1 实现文件的打开与读取

cpp 复制代码
void Widget::on_btnOpen_clicked()
{
    // 打开文件选择对话框,默认打开路径为"C:/Users/mi/Desktop/Qt Project",只显示txt文件
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                                                    "C:/Users/mi/Desktop/Qt Project",        // 默认路径
                                                    tr("Text files (*.txt)"));               // 限制为txt文件格式

    // 打印选中文件的路径
    qDebug() << fileName << endl;

    // 1. 尝试打开选中的文件
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "File open error";
        return;
    }

    // 2. 清空 QTextEdit 中的现有内容
    ui->textEdit->clear();

    QTextStream in(&file);
    in.setCodec("UTF-8");

    // 3. 逐行读取文件内容并追加到 QTextEdit 中
    while (!in.atEnd()){
        QString line = in.readLine();
        ui->textEdit->append(line);
    }

    // 4. 关闭文件
    file.close();
}

4.2 实现文件的保存

cpp 复制代码
// 1.打开文件对话框,选择保存的路径和文件名
QString fileName = QFileDialog::getSaveFileName(this, tr("保存文件"),
                                "C:/Users/mi/Desktop/untitled.txt",
                                tr("Text files (*.txt *doc)"));  // 只显示 .txt 和 .doc 文件类型

// 2.输出用户选择的文件名到控制台
qDebug() << fileName << endl;

// 3.设置要保存的文件名(路径)
QFile file;
file.setFileName(fileName);

// 4.以"只写"模式和"文本"类型打开文件
if(file.open(QIODevice::WriteOnly | QIODevice::Text)){
    qDebug() << "file open error";
}

// 5.将 QTextEdit 的内容写入文件
QTextStream out(&file);
out.setCodec("UTF-8");

out << ui->textEdit->toPlainText();

// 6.关闭文件
file.close();

5. 创建下拉列表控件类QComboBox

5.1 第一种方法,直接在ui界面中给QComboBox组件添加选择项

5.2 第二种方法,通过代码的方式为QComboBox添加选择项

cpp 复制代码
#include <QComboBox>
#include <QVBoxLayout>
#include <QWidget>

class ComboBoxDemo : public QWidget {
    Q_OBJECT

public:
    ComboBoxDemo() {
        // 创建一个 QComboBox 对象
        QComboBox *comboBox = new QComboBox(this);

        // 添加选项
        comboBox->addItems({"选项 1", "选项 2", "选项 3"});
        
        // 设置为可编辑
        comboBox->setEditable(true);

        // 连接信号和槽函数,当选择项改变时触发 onSelectionChanged(int)
        connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onSelectionChanged(int)));

        // 创建垂直布局并将 QComboBox 添加到其中
        QVBoxLayout *layout = new QVBoxLayout(this);
        layout->addWidget(comboBox);
    }

private slots:
    // 当选中的项改变时执行的处理逻辑
    void onSelectionChanged(int index) {
        // 在这里添加你想要的逻辑
        qDebug() << "当前选中的索引是: " << index;
    }
};

6.为记事本项目添加行列显示

6.1 解决思路:每当我输入一个字,光标位置就会发生改变,因此我需要去帮助文档中查找TextEdit中的光标位置发生改变的信号。可以进行信号与槽的连接,当光标位置改变发出信号,被槽函数捕捉,槽函数通过某个函数去获取到光标的行列值并且显示到QLabel上面

6.2 去帮助文档里面找QTextEdit的Signal信号,去找功能是光标位置发生改变时的函数

6.3接着去构造函数中添加connect函数连接该信号与槽函数

cpp 复制代码
connect(ui->textEdit, SIGNAL(cursorPositionChanged()), this, SLOT(oncursorPositionChanged()));

6.4 继续去帮助文档里面找QTextEdit的公有函数,功能是获取当前的行列,可以看到该函数的返回值是一个QTextCursor类的值,点击该函数查看具体的用法

cpp 复制代码
//====================================================================================
//当QtextEdit中的光标位置发生移动时,将行列显示到右下角的QLabel上面
//====================================================================================
void Widget::oncursorPositionChanged(){
    QTextCursor cursor = ui->textEdit->textCursor();
    // 当前光标的行数
    QString blockNum = QString::number(cursor.blockNumber()+1);
    //当前光标的列数
    QString columnNum = QString::number(cursor.columnNumber()+1);

    const QString labelMes="L:"+blockNum+",C:"+columnNum+"";

    // 修改QLabel中的文本内容
    ui->labelPosition->setText(labelMes);
}

7.记事本实现当前行高亮显示

帮助文档 ------> 搜索QTextEdit ------> Public Functions

------> void QTextEdit::setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections)

可以看到setExtraSelections函数的参数是一个QList列表,并且列表中的元素是ExtraSelection类型的,那么我们进一步点击ExtraSelection查看,可以看到该类型包含一下俩个参数,用于定位当前位置和颜色属性。

cpp 复制代码
void Widget::oncursorPositionChanged() {
    QTextCursor cursor = ui->textEdit->textCursor();

    // 当前光标的行数
    QString blockNum = QString::number(cursor.blockNumber() + 1);
    // 当前光标的列数
    QString columnNum = QString::number(cursor.columnNumber() + 1);

    const QString labelMes = "L:" + blockNum + ", C:" + columnNum;

    // 修改 QLabel 中的文本内容
    ui->labelPosition->setText(labelMes);

    // 设置当前行高亮
    QList<QTextEdit::ExtraSelection> extraSelections;

    // 创建 ExtraSelection 对象并设置光标及颜色
    QTextEdit::ExtraSelection ext;
    ext.cursor = cursor;                 // 使用当前光标定位
    QBrush qBrush(Qt::blue);             // 高亮颜色
    ext.format.setBackground(qBrush);    // 设置背景颜色
    ext.format.setProperty(QTextFormat::FullWidthSelection, true);  // 设置为全宽选择

    // 将设置好的 ExtraSelection 添加到列表中
    extraSelections.append(ext);

    // 设置 QTextEdit 的额外选择项
    ui->textEdit->setExtraSelections(extraSelections);
}

7.1 ExtraSelection简介

QTextEdit:: ExtraSelection是一个在QTextEdit中用来表示额外的文本选择和高亮的结构。

1.ExtraSelection 结构体:**QTextEdit:: ExtraSelection 是一个结构体,包含了两个主要成员 QTextCursor和QTextCharFormat。QTextCursor表示在文本中的一个位置或者区间,而QTextCharFormat用于定义这个区间的格式,比如背景颜色、字体等。

2.设置ExtraSelection:**你可以创建一个或多个ExtraSelection对象,为它们设置相应的光标位置和格式,然后通过QTextEdit的setExtraSelections方法将这些对象应用到文本编辑器中。这样,你可以对文本的特定部分应用特定的格式,而不影响其他文本。

3.高亮当前行:**要高亮显示当前行,你需要在cursorPositionChanged()信号的槽函数中创建一个ExtraSelection对象。使用当前的QTextCursor对象(通过textCursor()方法获取)来确定当前行的位置,并设置背景颜色为你选择的高亮颜色。

QTextCharFormat类是Qt框架中的一部分,用于描述文本字符的格式。这个类提供了丰富的接口来设置和获取文本字符的各种属性,如字体、颜色、背景色等。QTextCharFormat通常用于富文本处理可以在像QTextEdit和QTextDocument这样的类中使用下面列出了QTextCharFormat的一些常用功能和方法:

1.设置和获取字体样式:

  • 使用setFont()方法设置字体。
  • 通过font()方法获取当前字体。

2.设置字体属性:

  • setFontWeight():设置字体的粗细。
  • setFontItalic():设置字体是否倾斜。
  • setFontUnderline():设置是否有下划线。

3.设置文本颜色和背景色:

  • setForeground():设置文本的前景色(即字体颜色)。
  • setBackground():设置文本的背景色。

4.其他文本属性:

  • setToolTip():设置文本的工具提示。
  • setAnchor():设置文本是否为超链接。
  • setAnchorHref():设置超链接的目标URL。
cpp 复制代码
#include <QApplication>
#include <QTextEdit>
#include <QTextCharFormat>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    // 创建 QTextEdit 编辑器
    QTextEdit editor;

    // 创建一个 QTextCharFormat 对象来定义文本格式
    QTextCharFormat format;
    format.setFontWeight(QFont::Bold);        // 设置字体为粗体
    format.setForeground(Qt::blue);           // 设置文本颜色为蓝色
    format.setBackground(Qt::yellow);         // 设置文本背景为黄色

    // 获取编辑器的 QTextCursor
    QTextCursor cursor = editor.textCursor();

    // 移动光标到文本开始位置,并插入带格式的文本
    cursor.movePosition(QTextCursor::Start);
    cursor.insertText("Hello, World!", format);

    // 显示编辑器窗口
    editor.show();

    // 启动应用程序事件循环
    return a.exec();
}

8.消息对话框QMessageBox

QMessageBox是Qt框架中用于显示消息框的一个类,它常用于向用户显示信息、询问问题或者报告错误。以下是QMessageBox的一些主要用途:

8.1示例代码

cpp 复制代码
#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();
}

8.2自定义按键

cpp 复制代码
// 创建消息框
        QMessageBox msgBox;
        msgBox.setWindowTitle("Message Title");            // 设置窗口标题
        msgBox.setText("保存对此文件所做修改?");             // 设置主要消息文本
        msgBox.setIcon(QMessageBox::Information);          // 设置图标为信息类型

        // 自定义按钮
        QPushButton *saveButton = msgBox.addButton(tr("保存"), QMessageBox::AcceptRole);            // 自定义保存按钮
        QPushButton *discardButton = msgBox.addButton(tr("不保存"), QMessageBox::DestructiveRole);  // 自定义不保存按钮
        QPushButton *returnButton = msgBox.addButton(tr("返回"), QMessageBox::RejectRole);          // 自定义返回按钮

        // 执行消息框并获取用户的响应
        msgBox.exec();

        // 用户点击了保存============================================================================
        if (msgBox.clickedButton() == saveButton) {
        }else if(msgBox.clickedButton() == discardButton){
        }

9. 实现快捷键功能

在Qt中实现快捷键功能通常涉及到QShortcut类的使用。下面是一个简单的代码示例,展示了如何在 Qt应用程序中为特定功能设置快捷键:

Ctrl + O 弹出文件选择对话框,用于打开某个文件

Ctrl + S 弹出文件保存对话框,进行保存文件

9.1 示例代码

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    // 创建一个快捷键 Ctrl + N 并关联到窗口
    QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+N"), this);

    // 当快捷键被按下时,显示一个消息框
    QObject::connect(shortcut, &QShortcut::activated, [this]() {
        QMessageBox::information(this, "Shortcut Activated", "Ctrl+N was pressed");
    });
    
    // 当快捷键被按下时,调用保存文件的槽函数
    QObject::connect(shortcut, &QShortcut::activated, this, &Widget::on_pushButton_clicked);
}

9.2快捷键实现放大和缩小字体

在帮助文档中看QTextEdit,public functions里面有字体相关的说明

但是我们仅仅从这些函数,无法获取到当前控件的字体,我们需要看它的父类

它的父类里面好像也没有,继续往下找

好像也没有,继续往下找

此时找到了font()函数,其属于QFont类,在该类下面包含了许多有关于字体相关的API

cpp 复制代码
QShortcut *shortZoomIn = new QShortcut(QKeySequence("Ctrl+Shift+="), this);

QObject::connect(shortZoomIn, &QShortcut::activated, [=](){
        QFont Font = ui->textEdit->font();     // 获取当前字体
        int fontSize = Font.pointSize();       // 获取当前字体大小
        QFont newFont("Arial", fontSize + 1);  // 改变当前字体大小
        ui->textEdit->setFont(newFont);
    });

10.Qt事件概念的引入

Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会经过: 事件派发->事件过滤->事件分发->事件处理几个阶段。

Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作,比如信号与槽就是一种事件(event)是由系统或者Qt本身在不同的场景下发出的。

当用户按下移动鼠标、敲下键盘,或者是窗口关闭大小发生变化隐藏或显示都会发出一个相应事件。一些事件在对用户操作做出响应时发出,如鼠标键盘事件等;

另一些事件则是由系统自动发出, 如计时器事件。每一个Qt应用程序都对应一个唯一的QApplication应用程序对象,然后调用这个对的 exec()函数,这样Qt框架内部的事件检测就开始了(程序将进入事件循环来监听应用程序的事件)。

10.1 在帮助文档中搜索QWidget可以看到很多有关事件的API

10.2重写事件:程序关闭之前进行询问

cpp 复制代码
// 鼠标进入窗口时
void Widget::enterEvent(QEvent *event)
{
    qDebug() << "mouse enter";

}

// 鼠标离开窗口时
void Widget::leaveEvent(QEvent *event)
{
    qDebug() << "mouse leave";
}

// 鼠标滚轮发生变化时
void Widget::wheelEvent(QWheelEvent *event)
{
    qDebug() << "mouse become";
    qDebug() << event->angleDelta();
}

// 窗口关闭时
void Widget::closeEvent(QCloseEvent *event)
{
    int ret = QMessageBox::warning(this, tr("提示!"),
                                    tr("确定退出应用程序吗?"),
                                    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();
}

10.3 用事件自定义出一个按键

自定义按键涉及到的事件有鼠标的进入,离开,点击

  • 在当前项目中添加一个mybutton类,并使其继承于QWidget
  • 来到mybutton的头文件中,添加保护类成员函数:事件函数。
  • 并通过Alt+Enter快捷键快速向mybutton.cpp中添加事件函数的框架。添加完后通过F4快捷键快速切换到mybutton.h头文件中
  • 接着实现该按键在最初始的状态就是一个图片,首先去mybutton.h头文件中添加一个私有成员 QPixmap pic;。然后去mybutton类的构造函数中利用pic对象去加载图片

    (注意在此之前先添加你需要的图片到整个工程文件中)

cpp 复制代码
#include "mybutton.h"
#include <QPainter>

myButton::myButton(QWidget *parent) : QWidget(parent)
{
    // 加载初始图片
    pic.load(":/icon/o1.png");
    // 设置按钮的固定大小为图片的大小
    //setFixedSize(pic.size());
    setFixedSize(100,100);
    // 刷新界面,触发 paintEvent 进行绘制
    update();
}

void myButton::enterEvent(QEvent *event)
{
    // 当鼠标进入按钮区域时,加载悬停状态的图片
    pic.load(":/icon/o3.png");
    // 刷新界面,更新显示图片
    update();
}

void myButton::leaveEvent(QEvent *event)
{
    // 当鼠标离开按钮区域时,恢复初始状态的图片
    pic.load(":/icon/o1.png");
    // 刷新界面,更新显示图片
    update();
}

void myButton::mousePressEvent(QMouseEvent *event)
{
    // 当鼠标按下时,加载点击状态的图片
    pic.load(":/icon/o2.png");
    // 刷新界面,更新显示图片
    update();
}

void myButton::paintEvent(QPaintEvent *event)
{
    // 创建一个 QPainter 对象,负责绘制图片
    QPainter painter(this);
    // 使用 QPainter 在按钮区域内绘制当前加载的图片
    painter.drawPixmap(rect(), pic);
}
  • 接着去到widget.cpp的ui界面中,添加一个Widget窗口组件,并提升其为myButton

10.4 如何给自定义按键进行信号与槽的绑定

(1)给 widget.h 中包含 #include "mybutton.h"

(2)给 mybutton.h 中 添加一个信号 void clicked();

(3)给 mybutton.c 中的点击事件中添加发送信号(发送点击事件时,切换图片,发送信号)

cpp 复制代码
void myButton::mousePressEvent(QMouseEvent *event)
{
    // 当鼠标按下时,加载点击状态的图片
    pic.load(":/icon/o2.png");
    // 刷新界面,更新显示图片
    update();
    // 发送点击信号
    emit clicked();
}
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 当检测到clicked信号时,通过Lambda表达式输出调试内容
    connect(ui->myBtn, &myButton::clicked, [=](){
        qDebug() << "myButton is clicked";
    });
}

10.5事件重写实现滚轮控制字体的放大与缩小

(1)在记事本项目中新建一个类MyTextEdit,使其继承与QTextEdit

(2) 向 mytextedit.h 中添加保护成员事件函数

cpp 复制代码
#ifndef MYTEXTEDIT_H
#define MYTEXTEDIT_H

#include <QTextEdit>


class MyTextEdit : public QTextEdit
{
public:
    MyTextEdit(QWidget *parent);
protected:
    void wheelEvent(QWheelEvent *e) override;    // 鼠标滚轮事件
    void keyPressEvent(QKeyEvent *e) override;   // 按键按下事件
    void keyReleaseEvent(QKeyEvent *e) override; // 按键松开事件
private:
    bool ctrlKeyPressed = 0;
};

#endif // MYTEXTEDIT_H

(3)mytextedit.cpp

cpp 复制代码
#include "mytextedit.h"
#include <QWheelEvent>
#include <QDebug>

// UStudent::UStudent(String name, int age, String class, String Id) : Student(String name, int age, String class)
MyTextEdit::MyTextEdit(QWidget *parent) : QTextEdit(parent)
{
}

// 鼠标滚轮事件
void MyTextEdit::wheelEvent(QWheelEvent *e)
{
    //qDebug() << e->angleDelta().y();   // 输出120代表鼠标滚轮向上,输出-120代表鼠标滚轮向下
    if(ctrlKeyPressed == 1){
        if(e->angleDelta().y()>0){
            zoomIn();                    // 字体放大
        }else if(e->angleDelta().y() < 0){
            zoomOut();                   // 字体缩小
        }

        e->accept();                     // 表明了该鼠标滚轮事件已被处理,而不会继续将该事件进一步传播
    }else{                               // 如果Ctrl按键没有被按下,只有鼠标滚轮事件,则由其父类执行鼠标滚轮默认操作
        QTextEdit::wheelEvent(e);
    }
}

// 键盘按键按下事件
void MyTextEdit::keyPressEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control){
        qDebug() << "ctrl Pressed";
        ctrlKeyPressed = 1;
    }
    QTextEdit::keyPressEvent(e);
}

// 键盘按键松开事件
void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control){
        qDebug() << "ctrl Release";
        ctrlKeyPressed = 0;
    }
    QTextEdit::keyReleaseEvent(e);
}

(4)提升原 textEdit为mytextedit

10.6事件过滤器

**派发------>过滤------>分发------>处理**

(通过修改子类代码的情况下修改事件的行为,属于修改事件的处理阶段)

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 在 Qt 的事件处理过程中,事件过滤器(Event Filter) 是一种强大的机制,可以在事件到达目标对象之前拦截并处理它。通过事件过滤器,你可以共享不同对象的事件处理逻辑,或者在父对象中集中处理某些特定的事件。以下是如何引入和使用事件过滤器的步骤: ### 1. 定义事件过滤器: 事件过滤器通常是一个继承自 QObject 的类,重写 QObject::eventFilter() 方法。这个方法会在事件传递到目标对象之前被调用。 ### 2. 安装事件过滤器: 使用 QObject::installEventFilter() 方法将事件过滤器安装到某个对象上。安装后,事件会在发送给目标对象之前先经过过滤器。例如,如果想在父窗口中过滤子窗口的事件,需要在父对象上调用 installEventFilter(),并传递子窗口作为参数。 ### 3. 实现事件过滤器逻辑: 在 eventFilter() 方法内部,你可以编写自定义逻辑来决定是否处理或忽略事件。如果返回 true,事件被处理,不会继续传递;如果返回 false,事件将继续传递给目标对象。 ### 4. 事件分发: 当事件发生时,Qt 首先会将事件发送到安装了事件过滤器的对象,调用 eventFilter()。 ### 5. 决定是否传递事件: 根据 eventFilter() 的返回值,Qt 决定是否继续向目标对象传递事件。如果返回 true,事件处理结束;如果返回 false,事件会继续传递给目标对象。 ### 6. 目标对象处理事件: 如果事件过滤器允许事件继续传递,目标对象将像没有过滤器时那样处理事件。 ### 事件过滤器的适用场景: - 当你想改变子类事件的行为,而不修改其代码。 - 当多个对象共享相同的事件处理逻辑。 |

第一步:去头文件声明事件过滤函数

cpp 复制代码
public:
bool eventFilter(QObject *watched, QEvent *event);

第二步:在Widget构造函数中为textEdit安装了事件过滤器,为滚轮字体做准备

cpp 复制代码
ui->textEdit->installEventFilter(this);
  • 第三步:实现过滤函数

先去帮助文档中查找QEvent,看看事件有哪些类型,我们此处需要的是鼠标滚轮事件和Ctrl按键按下事件,但是由于一次只能捕捉一个事件,所以我们需要通过Api去判断Ctrl按键是否被按下,就不使用Ctrl按键按下事件

  • 第四步:根据经验可知,可通过QGuiApplication类中的下面函数去判断哪个按键被按下

Qt::KeyboardModifiers QGuiApplication::keyboardModifiers()

该Api返回值是**Qt::KeyboardModifiers**类型的,点击进去可以看到该类型包含以下按键,我们需要的是返回值为Ctrl按键

  • 第五步:开始编写过滤函数
cpp 复制代码
// 事件过滤函数
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type() == QEvent::Wheel){
        if(QGuiApplication::keyboardModifiers() == Qt::ControlModifier){
            qDebug() << "Ctrl and Wheel pressed";
            //此处需要你强制类型转换,因为QEvent类中并不包含QwheelEvent类的angleDelta()函数
            QWheelEvent *wheelEvent = (QWheelEvent *)event;
            if(wheelEvent->angleDelta().y() > 0){
                zoomInText();
            }else if(wheelEvent->angleDelta().y() < 0){
                zoomOutText();
            }
            return true; //不再继续传递
        }

        return false;
    }
}

在 C++ 中,强制类型转换(或类型转换)是将变量从一种类型转换为另一种类型的方式。C++ 提供了四种强制转换运算符,每种都有特定的用途和适用场景:

相关推荐
skaiuijing1 小时前
Sparrow系列拓展篇:消息队列和互斥锁等IPC机制的设计
c语言·开发语言·算法·操作系统·arm
雯0609~3 小时前
c#:winform调用bartender实现打印(学习整理笔记)
开发语言·c#
胜天半子_王二_王半仙4 小时前
c++源码阅读__smart_ptr__正文阅读
开发语言·c++·开源
沐泽Mu4 小时前
嵌入式学习-C嘎嘎-Day08
开发语言·c++·算法
Non importa4 小时前
汉诺塔(hanio)--C语言函数递归
c语言·开发语言·算法·学习方法
LinuxST4 小时前
27、基于Firefly-rk3399中断休眠唤醒实验(按键中断)
linux·开发语言·stm32·嵌入式硬件
Tony_long74834 小时前
Python学习——猜拳小游戏
开发语言·python·学习
跳动的梦想家h4 小时前
黑马点评 秒杀下单出现的问题:服务器异常---java.lang.NullPointerException: null(已解决)
java·开发语言·redis
ac-er88885 小时前
PHP 二分法查找算法
开发语言·算法·php
流着口水看上帝5 小时前
JavaScript完整原型链
开发语言·javascript·原型模式