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 

3. 文件操作类QTextStream

4. 文件选择对话框 QFileDialog

4.1 实现文件的打开与读取

4.2 实现文件的保存

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

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

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

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

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

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

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

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

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

7.1 ExtraSelection简介

8.消息对话框QMessageBox

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

9. 实现快捷键功能

9.1 示例代码

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

10.Qt事件概念的引入

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

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

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

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

10.6事件过滤器


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 

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

//==========================================================================
// 读取
//==========================================================================
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 实现文件的打开与读取

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 实现文件的保存

// 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添加选择项

#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函数连接该信号与槽函数

connect(ui->textEdit, SIGNAL(cursorPositionChanged()), this, SLOT(oncursorPositionChanged()));

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

//====================================================================================
//当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查看,可以看到该类型包含一下俩个参数,用于定位当前位置和颜色属性。

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。
#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示例代码

#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自定义按键

// 创建消息框
        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 示例代码

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

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重写事件:程序关闭之前进行询问

// 鼠标进入窗口时
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对象去加载图片

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

#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 中的点击事件中添加发送信号(发送点击事件时,切换图片,发送信号)

void myButton::mousePressEvent(QMouseEvent *event)
{
    // 当鼠标按下时,加载点击状态的图片
    pic.load(":/icon/o2.png");
    // 刷新界面,更新显示图片
    update();
    // 发送点击信号
    emit clicked();
}
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 中添加保护成员事件函数

#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

#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. 目标对象处理事件: 如果事件过滤器允许事件继续传递,目标对象将像没有过滤器时那样处理事件。 ### 事件过滤器的适用场景: - 当你想改变子类事件的行为,而不修改其代码。 - 当多个对象共享相同的事件处理逻辑。

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

public:
bool eventFilter(QObject *watched, QEvent *event);

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

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

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

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

Qt::KeyboardModifiers QGuiApplication::keyboardModifiers()

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

  • 第五步:开始编写过滤函数

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/907405.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【在Linux世界中追寻伟大的One Piece】Socket编程TCP(续)

目录 1 -> V2 -Echo Server多进程版本 2 -> V3 -Echo Server多线程版本 3 -> V3-1 -多线程远程命令执行 4 -> V4 -Echo Server线程池版本 1 -> V2 -Echo Server多进程版本 通过每个请求&#xff0c;创建子进程的方式来支持多连接。 InetAddr.hpp #pragma…

为什么可视化大屏要有动态效果,都有哪些类型的效果。

可视化大屏已成为企业和组织展示关键信息的重要工具。这些大屏不仅需要清晰地传达数据&#xff0c;还要吸引观众的注意力并提供深刻的洞察。动态效果在这一过程中扮演着至关重要的角色。 动态效果的重要性 动态效果在可视化大屏中的应用&#xff0c;基于以下几个核心原因 吸…

【C/C++】字符/字符串函数(0)(补充)——由ctype.h提供

零.导言 除了字符分类函数&#xff0c;字符转换函数也是一类字符/字符串函数。 C语言提供了两种字符转换函数&#xff0c;分别是 toupper &#xff0c; tolower。 一.什么是字符转换函数&#xff1f; 顾名思义&#xff0c;即转换字符的函数&#xff0c;如大写字母转小写字母&am…

Hive数据库操作语法

数据类型 内部表和外部表 内部表 &#xff08;CREATE TABLE table_name ......&#xff09;未被external关键字修饰的即是内部表&#xff0c; 即普通表。 内部表又称管理表,内部表数据存储的位置由hive.metastore.warehouse.dir参数决定&#xff08;默认&#xff1a;/user/h…

线程基础知识、jmm(Java内存模型)

目录 线程基础知识 并发与并行 进程和线程 线程优先级 创建线程的方式主要有三种 休眠 作出让步 join() 方法 线程协作注意什么 理解线程状态 选择合适的协作工具 共享资源的访问控制 避免竞争条件 创建线程几种方式 线程状态&#xff0c;状态之间切换 新建&…

图解大模型训练系列:序列并行2,DeepSpeed Ulysses

最近已有不少大厂都在秋招宣讲&#xff0c;也有一些已在 Offer 发放阶段了。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行…

MP4650模块改为固定电压记录

目标 这种电源模块&#xff0c;可调电位器质量不太好&#xff0c;可调输出电压改为固定电压。 方法 步骤 按照下图&#xff0c;将计算得到的R1 补到 待添加电阻处。 结论 作者使用输出5V&#xff0c;R1电阻使用5.1K&#xff0c;得到输出电压4.8V&#xff1b; 测试输出电流1A…

51单片机教程(二)- 创建项目

1 创建项目 创建项目存储文件夹&#xff1a;C51Project 打开Keil5软件&#xff0c;选择 Project -> New uVision Project&#xff1a; 选择项目路径&#xff0c;即刚才创建的文件夹 选择芯片&#xff0c;选择 Microchip&#xff08;微型集成电路&#xff09;&#xff0…

STM32 HAL库 SPI驱动1.3寸 OLED屏幕

目录 参考硬件引脚与接线 点亮屏幕CubeMX 配置OLED 驱动程序代码 参考 基于STM32F103C8T6最小系统板HAL库CubeMX SPI驱动7针 OLED显示屏&#xff08;0.96寸 1.3寸通用&#xff09;0.96 oled HAL库驱动 SPI STM32SPI驱动0.96/1.3寸 OLED屏幕&#xff0c;易修改为DMA控制STM32驱…

通过分解质因数求若干个数的最小公倍数

求最小公倍数的常规方法回顾 暴力枚举法 long long work(long long a,long long b) {for(long long imax(a,b);;i)if(i%a0&&i%b0)return i; }大数翻倍法 long long work(long long a,long long b) {if(a<b) swap(a,b);for(long long ia;;ia) // i 是 a 的倍数&#…

突出显示与条件匹配的列值

Goto Appearance and Conditional Formatting 外观和条件格式 突出显示与条件匹配的列值 本教程说明如何将条件格式应用于 GridControl 中的 Market Share 列&#xff0c;以突出显示与特定条件匹配的单元格。此示例突出显示小于 20% 的 Market Share 列值。 要在设计时创建新…

node.js下载、安装、设置国内镜像源(永久)(Windows11)

目录 node-v20.18.0-x64工具下载安装设置国内镜像源&#xff08;永久&#xff09; node-v20.18.0-x64 工具 系统&#xff1a;Windows 11 下载 官网https://nodejs.org/zh-cn/download/package-manager 版本我是跟着老师选的node-v20.18.0-x64如图选择 Windows、x64、v20.18…

嵌入式开发教程之Linux下IO流

一、文件的概念和类型 文件基础&#xff1a; 概念&#xff1a;一组相关数据的有序集合&#xff0c;文件名、路径。通过文件名指定访问什么文件。 文件类型&#xff1a; 常规文件 r&#xff0c;分为&#xff1a;普通文件&#xff0c;文本文件&#xff08;可见字符&#xff09…

【Python】Python自习课:第一个python程序

【Python】Python自习课&#xff1a;第一个python程序

MySQL【二】

查询列 SELECT [ALL | DISTINCT ] * | 列名1[,……列名n] FROM 表名; 查询所有选课学生的学号&#xff0c;结果去除重复值 select distinct sno from sc; 选择行 查询满足条件的数据集 SELECT 字段列表 FROM 表名 WHERE 查询条件 查询不属于数学系或外国语系的学生全部信息 …

#渗透测试#SRC漏洞挖掘# 信息收集-Shodan进阶之Mongodb未授权访问

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

Redis 位图实现签到之长时间未签到预警

#目前通行系统项目中有一个新需求【通过对通行记录数据定时分析&#xff0c;查询出长时间没 有刷卡/刷脸通行的学生】 #一看到通行签到相关&#xff0c;就想到了redis的位图&#xff0c;理由也有很多帖子说明了&#xff0c;最大优点占用空间小。 一.redis命令行 SETBIT&#…

python mac vscode 脚本文件的运行

切换到脚本文件的目录下 路径的修改 当前文件组织形式&#xff1a; 脚本文件在文件夹下&#xff1a; 赋予权限&#xff1a;chmod x ./scripts/fscd_test.sh 运行&#xff1a;./scripts/fscd_test.sh

人脑与机器连接:神经科技的伦理边界探讨

内容概要 在当今科技飞速发展的时代&#xff0c;人脑与机器连接已成为一个引人注目的前沿领域。在这一背景下&#xff0c;神经科技的探索为我们打开了一个全新的世界&#xff0c;从脑机接口到人工智能的飞跃应用&#xff0c;不仅加速了技术的进步&#xff0c;更触动了我们内心…

[论文阅读] | 智能体长期记忆

更新记录&#xff1a; 2024.11.2 人大高瓴长期记忆综述 文章目录 人大高瓴长期记忆综述智能体与环境交互记忆的来源/形式/操作来源&#xff1a;(1)当前任务历史信息 (2)其他任务的信息 (3)外部知识形式&#xff1a;如何表达记忆的内容&#xff0c;通过(1)文本 (2)参数(训练到模…