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++ 提供了四种强制转换运算符,每种都有特定的用途和适用场景:

相关推荐
用户805533698034 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner4 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz9 天前
QML Hello World 入门示例
qt
xcyxiner12 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner12 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner13 天前
DicomViewer (添加模型类)3
qt
xcyxiner13 天前
DicomViewer (目录调整) 2
qt
xcyxiner13 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00615 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术15 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript