Qt之快捷键、事件处理、自定义按键——完成记事本项目

快捷键

我们电脑中的记事本中还支持快捷键,如

"CTRL+O"打开文件、"CTRL+S"保存文件

在Qt中使用QShortcut这个类创建快捷键

在.cpp文件的构造函数中创建QShortcut对象,绑定打开文件和保存文件的槽函数

放大缩小字体

还是在.cpp的构造函数中编写代码

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setLayout(ui->verticalLayout);
    ui->widget_2->setLayout(ui->horizontalLayout_2);
    connect(ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(oncurrentIndex(int)));
    connect(ui->textEdit,SIGNAL(cursorPositionChanged()),this,SLOT(oncursorPosition()));
    
    QShortcut *shortcutOpen=new QShortcut(QKeySequence(tr("Ctrl+O","File|Open")),this);        //添加快捷键
    QShortcut *shortcutSave=new QShortcut(QKeySequence(tr("Ctrl+S","File|Save")),this);
    connect(shortcutOpen,&QShortcut::activated,[=](){on_Bopen_clicked();});                    //绑定信号与槽(指针)
    connect(shortcutSave,&QShortcut::activated,[=](){on_Bsave_clicked();});
    
    QShortcut *shortcutZoomBig=new QShortcut(QKeySequence(tr("Ctrl+Shift+=","File|Save")),this);   //ctrl、shift、+号同时按下(+与=在同一个位置)
    QShortcut *shortcutZoomSmall=new QShortcut(QKeySequence(tr("Ctrl+Shift+-","File|Save")),this); 
    connect(shortcutZoomBig,&QShortcut::activated,[=](){
        QFont font = ui->textEdit->font();            //获取当前字体信息
        int fontSize = font.pointSize();              //获取当前字体大小
        if(fontSize==-1) return;
        int newfontSize=fontSize+1;                   //改变字体大小
        font.setPointSize(newfontSize);               //设置新字体大小
        ui->textEdit->setFont(font);
    });  
    connect(shortcutZoomSmall,&QShortcut::activated,[=](){
        QFont font = ui->textEdit->font();            //获取当前字体信息
        int fontSize = font.pointSize();              //获取当前字体大小
        if(fontSize==-1) return;
        int newfontSize=fontSize-1;                   //改变字体大小
        font.setPointSize(newfontSize);               //设置新字体大小
        ui->textEdit->setFont(font);
    });   
}

事件处理

事件是 Qt 程序与用户(或操作系统)交互的基本单元:用户按下鼠标、键盘输入、窗口被遮挡或暴露、定时器到期......都会产生一个 QEvent 对象。

过去我们常用"信号-槽"机制来处理用户动作,但信号-槽只能覆盖 Qt 已定义好的"高层语义",遇到"关闭窗口时询问是否保存""拖拽窗口时限制范围"这类底层或组合行为,就必须介入真正的事件处理流程。

在 Qt 中,事件处理分为四个连贯的步骤:

  1. 事件派发(dispatch):QApplication::notify() 把事件发给目标对象;

  2. 事件过滤(filter):沿途的所有 QObject::eventFilter() 都有机会截断或修改事件;

  3. 事件分发(delivery):目标对象内部的 QWidget::event() 根据事件类型再细分;

  4. 事件处理(handle):具体虚函数如 mousePressEvent()closeEvent() 最终被执行。

在Qwidget中的保护成员中,还有如下这些事件处理函数,如closeEvent()可以关闭窗口,我们重写事件处理函数也可以在一定程度上处理事件。

事件重写

我们再来添加一个关闭窗口时的弹窗询问

打开.h文件,声明重写closeEvent()事件处理函数(widget继承于Qwidget)

同时按下"ALT+ENTER",在.cpp文件中添加实现

cpp 复制代码
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::Yes|QMessageBox::No);      //弹窗
    switch (ret) {
        case QMessageBox::Yes:
            event->accept();        //QCloseEvent继承于QEvent,accept接受事件,ignore忽略 
            break;
       case QMessageBox::No:
            event->ignore();
            break;
    }
            
}

自定义按键

按键个性化设置

新建一个项目(同前),然后自定义一个按钮

右键项目,点击"Add New"

点击"C++ Class",点击"choose"

继承于QWidget,点击"下一步",点击"完成"

需要在.h文件中声明的成员如下

再次右键项目名称,点击"Add New",添加一个Qt的资源文件

点击"Add Files",选择3张图片样式添加(在项目文件下添加),"CTRL+S"保存

在.cpp文件中实现重写逻辑

右键复制图片文件地址

cpp 复制代码
#include "mybutton.h"

#include <QPainter>

MyButton::MyButton(QWidget *parent) : QWidget(parent)
{
    pic.load(":/p1.png");   //加载图片(初始图片)
    setFixedSize(pic.size());  //设置按键大小为图片大小
    update();                  //刷新,触发paintEvent()
}

void MyButton::mousePressEvent(QMouseEvent *event)    
{
    pic.load(":/p3.png");
    update();
}

void MyButton::leaveEvent(QEvent *event)
{
    pic.load(":/p1.png");
    update();    
}

void MyButton::enterEvent(QEvent *event)
{
    pic.load(":/p2.png");
    update();    
}

void MyButton::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);                    //绘画师
    painter.drawPixmap(rect(),pic);            //绘制图像(矩形,位图)
    
}

打开.ui文件,托入一个widget控件,右键,点击"提升为"

输入新按钮的类的名称,点击"添加"

点击运行文件,按钮图标能正常转换

这样自定义后按键的形状就能随自己设计,更好看一些(可以用图片等)

自定义按键的信号与槽

在"button.h"文件中声明点击信号

在widget.cpp中引入button的头文件

connect绑定信号与槽

并在button.cpp文件,在鼠标信号点击处,发送点击信号

点击"打开"按钮后,能正常发射信号

事件重写实现滚轮放大缩小字体

标准的QTextEdit控件并不支持"CTAL+鼠标滚轮",所以我们要自定义一个MyTextEdit出来,再将notebook原来的textEdit提升为我们自定义的textEdit类(原代码.c文件不用修改,都是继承于QtextEdit实现)

右键项目名称,新建一个类文件

标注父控件

在我们的MyTextEdit构造时还需标注父控件,使MyTextEdit与ui中的TextEdit联系起来(ui中所有控件都有QWidget这个父亲)

"ALT+ENTER"添加构造函数的实现(把原来的删掉)

cpp 复制代码
MyTextEdit::MyTextEdit(QWidget *parent):QTextEdit(parent)    //调用QtextEdit的构造函数实现
{
    
}

再在.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;           //按键松开事件
};

#endif // MYTEXTEDIT_H

提升TextEdit

在ui中右键TextEdit,"提升为"

然后右边可以看到已经提升过来了

代码实现

放大和缩小字体的代码与之前快捷键实现重复了,所以直接把之前那段代码用函数封装调用就好了

widget.h添加声明

widget.cpp添加实现

使用事件函数基本的使用,我们已经能写出大致框架,但我们要实现的应该是"CTRL+滚轮"实现,但滚轮能够上下滑动

我们只要添加一个bool型的变量,使同时操作时再调用函数就可以了

以及除了同时按下,正常操作的反应要继承下来

cpp 复制代码
#include "mytextedit.h"

#include <QCloseEvent>

MyTextEdit::MyTextEdit(QWidget *parent):QTextEdit(parent)    //调用QtextEdit的构造函数实现
{

}

void MyTextEdit::wheelEvent(QWheelEvent *e)
{
    if(ctrlKeyPressed==1){
        if(e->angleDelta().y()>0){                           //上滑缩小
            zoomIn();
        }else if(e->angleDelta().y()<0){
            zoomOut();
        }
        e->accept();                                         //处理完毕
    }else{
        QTextEdit::wheelEvent(e);                             //正常执行QTextEdit的滚轮事件
    }
}

void MyTextEdit::keyPressEvent(QKeyEvent *e)
{
    if(e->key()==Qt::Key_Control){                          //Ctrl按下
        ctrlKeyPressed=1;
    }
    QTextEdit::keyPressEvent(e);                            //按键按下执行
}

void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
{
    if(e->key()==Qt::Key_Control){                          //Ctrl释放
        ctrlKeyPressed=0;
    }
    QTextEdit::keyReleaseEvent(e);
}

事件过滤器

对于Qt事件,我们主要把中重点放在事件处理和事件过滤

事件过滤器适用于:当你不想在修改子代码的情况下改变事件的行为(如上面的情况不添加新的类)。可在事件到达目标对象之前进行拦截和处理

先在.h文件添加声明

安装事件过滤器

在事件过滤器中,我们既要检测滚轮,又要检测"Ctrl"是否被按下。若单使用QEvent事件,检测滚轮会调用一次,检测ctrl按下又会调用一次。则两个事件不能同时被检测,所以我们换种方式检测滚轮。

cpp 复制代码
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type()==QEvent::Wheel){             //事件是滚轮事件
        if(QGuiApplication::keyboardModifiers()==Qt::ControlModifier){    //ctrl被按下
            QWheelEvent *weelEvent=dynamic_cast<QWheelEvent*>(event);                   //转换类型
            if(weelEvent->angleDelta().y()>0){
                zoomIn();
            }else{
                zoomOut();
            }
            return true;                           //事件已执行
        }
        return false;                              //若ctrl没被按下,事件继续传递给目标对象
    }
}

至此,我们的记事本项目简单完成!

下图为up主老陈的总结

相关推荐
Source.Liu2 小时前
【Pywinauto库】12.1 pywinauto.backend 后端内部实施模块
开发语言·windows·python·自动化
晚云与城2 小时前
今日分享:C++ deque与priority_queue
开发语言·c++
半梦半醒*2 小时前
正则表达式
linux·运维·开发语言·正则表达式·centos·运维开发
不吃洋葱.2 小时前
Bean.
java·开发语言
我星期八休息2 小时前
深入理解跳表(Skip List):原理、实现与应用
开发语言·数据结构·人工智能·python·算法·list
蒋星熠2 小时前
如何在Anaconda中配置你的CUDA & Pytorch & cuNN环境(2025最新教程)
开发语言·人工智能·pytorch·python·深度学习·机器学习·ai
Quz2 小时前
QML Charts组件之折线图的鼠标交互
qt
We....3 小时前
Java分布式编程:RMI机制
java·开发语言·分布式
€8113 小时前
Java入门级教程17——利用Java SPI机制制作验证码、利用Java RMI机制实现分布式登录验证系统
java·开发语言·java spi机制·远程传输数据