Qt学习笔记第71到80讲

第71讲 事件过滤器的方式实现滚轮按键放大

基本概念

事件体系(事件派发 -> 事件过滤->事件分发->事件处理)中,程序员主要操作的是事件分发与事件处理。我们之前已经通过继承QTextEdit来重写事件实现Ctrl加滚轮的检测,还有一种处理方式,叫做事件过滤器 在Qt的事件处理过程中,引入事件过滤器(Event Filter)可以让你在事件达到目标对象之前进行拦截和处理。这是一种强大的机制,允许你在不同对象间共享事件处理逻辑或在父对象中集中处理特定事件。

下面是加入事件过滤器的步骤:
事件过滤器特别适用于以下情况:
①当你想在不修改子类代码的情况下改变事件的行为。
②当多个对象需要共享相同的事件处理逻辑。
③当你需要在更高的层级上监控或修改应用程序的事件流。
通过使用事件过滤器, Qt 应用程序可以获得更大的灵活性和更细粒度的事件处理控制。

编程步骤

①在Widget构造函数内部安装过滤器(函数体内第二行)

Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->textEdit->installEventFilter(this);

    QShortcut *shortcutOpen = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),
                                        this);
    QShortcut *shortcutSave = new QShortcut(QKeySequence(tr("Ctrl+S", "File|Save")),
                                        this);
    QShortcut *shortcutEnlarge = new QShortcut(QKeySequence(tr("Ctrl+Shift+=", "File|Enlarge")),
                                        this);
    QShortcut *shortcutReduce = new QShortcut(QKeySequence(tr("Ctrl+Shift+-", "File|Reduce")),
                                        this);

    connect(shortcutOpen,&QShortcut::activated,[=](){on_btnOpen_clicked();});
    connect(shortcutSave,&QShortcut::activated,[=](){on_btnSave_clicked();});
    connect(shortcutEnlarge,&QShortcut::activated,[=](){textEditEnlarge();});
    connect(shortcutReduce, &QShortcut::activated,[=](){textEditReduce();});

    this->setLayout(ui->verticalLayout);
    ui->widgetBottom->setLayout(ui->horizontalLayout);

    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),
    this,SLOT(onCurrentIndexChanged(void)));

    connect(ui->textEdit,SIGNAL(cursorPositionChanged()),
    this,SLOT(onCursorPositionChanged()));
}
②在Widget类内部添加bool类型的事件过滤器函数声明
    bool eventFilter(QObject *watched,QEvent *event);

③在Widget.cpp文件内做出实现,引入了新的类型QGuiApplication

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    //滚轮滑动时用keyboardModifiers方法捕获Ctrl按键是否按下
    if(event->type()==QEvent::Wheel)
    {
        if(QGuiApplication::keyboardModifiers()==Qt::ControlModifier)
        {
            QWheelEvent *wheelEvent=dynamic_cast<QWheelEvent *>(event);
            if(wheelEvent->angleDelta().y()>0)
            {
              textEditEnlarge();
            }else if(wheelEvent->angleDelta().y()<0){
              textEditReduce();
            }
            return true;
        }
    }
    return false;
}

第72讲 记事本项目总结

分享一下现在的两种实现方式:
①自定义键盘按键事件
widget.cpp
#include "widget.h"
#include "ui_widget.h"

#include <QFileDialog>
#include <QDebug>
#include <QList>
#include <QColor>
#include <QMessageBox>
#include <QShortcut>

Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QShortcut *shortcutOpen = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),
                                        this);
    QShortcut *shortcutSave = new QShortcut(QKeySequence(tr("Ctrl+S", "File|Save")),
                                        this);
    QShortcut *shortcutEnlarge = new QShortcut(QKeySequence(tr("Ctrl+Shift+=", "File|Enlarge")),
                                        this);
    QShortcut *shortcutReduce = new QShortcut(QKeySequence(tr("Ctrl+Shift+-", "File|Reduce")),
                                        this);

    connect(shortcutOpen,&QShortcut::activated,[=](){on_btnOpen_clicked();});
    connect(shortcutSave,&QShortcut::activated,[=](){on_btnSave_clicked();});
    connect(shortcutEnlarge,&QShortcut::activated,[=](){textEditEnlarge();});
    connect(shortcutReduce, &QShortcut::activated,[=](){textEditReduce();});

    this->setLayout(ui->verticalLayout);
    ui->widgetBottom->setLayout(ui->horizontalLayout);

    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),
    this,SLOT(onCurrentIndexChanged(void)));

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

Widget::~Widget()
{
    delete ui;
}

void Widget::textEditEnlarge()
{
    //获取当前TextEdit内的字体信息
    QFont font=ui->textEdit->font();
    //获取当前字体的大小
    int fontSize=font.pointSize();
    if(fontSize==-1) return;

    //改变大小,并设置字体大小
    int newFontSize=fontSize+1;
    font.setPointSize(newFontSize);
    ui->textEdit->setFont(font);
}

void Widget::textEditReduce()
{
    //获取当前TextEdit内的字体信息
    QFont font=ui->textEdit->font();
    //获取当前字体的大小
    int fontSize=font.pointSize();
    if(fontSize==-1) return;

    //改变大小,并设置字体大小
    int newFontSize=fontSize-1;
    font.setPointSize(newFontSize);
    ui->textEdit->setFont(font);
}


void Widget::on_btnOpen_clicked()
{
    QString fileName=QFileDialog::getOpenFileName(this,tr("Open File"),
    "E:\\6_Qt Projects\\31_NotepadCodec\\files",tr("Text(*.txt *.doc)"));
    //QFileDialog限制程序可打开的文件形式为txt文件或者doc文本

    ui->textEdit->clear();
    //每次打开文件时清除控件区域“textEdit”

    file.setFileName(fileName);

    if(!file.open(QIODevice::ReadWrite|QIODevice::Text))
    {
        qDebug()<<"file open error";
    }

    this->setWindowTitle(fileName+"-NotesBook");

    QTextStream in(&file);

    QString str=ui->comboBox->currentText();
    const char* c_str=str.toStdString().c_str();

    in.setCodec(c_str);

    while(!in.atEnd())
    {
        QString context=in.readLine();
        //qDebug()<<qPrintable(context);

        ui->textEdit->append(context);
        //将读取到的每行内容通过 append 方法添加到界面的文本编辑框(ui->textEdit)中
    }

    // 将此时ui->textEdit中的文本内容保存到initialText变量中,作为初始文本
     initialText = ui->textEdit->toPlainText();
    //主动设置焦点(重要,解决了点击textEdit控件区域之后才能使用滚轮缩放的Bug)
     ui->textEdit->setFocus(Qt::OtherFocusReason);
}

void Widget::on_btnSave_clicked()
{
    //如果当前没有文件打开,就弹窗让用户选择新文件,创建新文件;
    //而不是原来那样,都弹出新的文件保存窗口
    if(!file.isOpen()){
        QString fileName = QFileDialog::getSaveFileName(this, tr("SaveFile"),
        "E:\\6_Qt Projects\\31_NotepadCodec\\files\\untitled file.txt",tr("Text (*.txt*.doc)"));

        file.setFileName(fileName);
        if(!file.open(QIODevice::WriteOnly | QIODevice::Text)){
           qDebug() << "file open error";
          }
       this->setWindowTitle(fileName + "- MyNoteBook");
    }else
    {
        // 如果文件已打开,先将文件指针移动到文件开头,准备覆盖原有内容
        file.seek(0);
        // 截断文件内容,清除原有内容
        file.resize(0);
    }

    //当保存被按下,不管是已有打开的文件还是上面if满足后用户选择新文件,
    //都要读取TextEdit内容并写入文件中
    QTextStream out(&file);
    out.setCodec(ui->comboBox->currentText().toStdString().c_str());
    QString context = ui->textEdit->toPlainText();
    out << context;
    initialText=ui->textEdit->toPlainText();
}

void Widget::on_btnClose_clicked()
{
    QString currentText = ui->textEdit->toPlainText();
    if(currentText!= initialText){
        int ret = QMessageBox::warning(this, tr("NotesBook Notice"),
                                       tr("The document has been modified.\n"
                                          "Do you want to save your changes?"),
                                       QMessageBox::Save | QMessageBox::Discard
                                       | QMessageBox::Cancel, QMessageBox::Save);

        switch (ret) {
        case QMessageBox::Save:
            // Save was clicked
            on_btnSave_clicked();
            ui->textEdit->clear();
            break;

        case QMessageBox::Discard:
            // Don't Save was clicked
            ui->textEdit->clear();
            if (file.isOpen()) {
                file.close();
                this->setWindowTitle("NotesBook");
            }
            break;

        case QMessageBox::Cancel:
            // Cancel was clicked
            break;

        default:
            // should never be reached
            break;
        }
    } else {
        ui->textEdit->clear();
        if (file.isOpen()) {
            file.close();
            this->setWindowTitle("NotesBook");
        }
    }
}

void Widget::onCurrentIndexChanged(void)
{
    ui->textEdit->clear();
    if(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值