QT记事本

news2024/11/29 2:52:27

QT记事本

  •  1.概述
  •  2.界面
    •   2.1 界面布局
    •   2.2 UI美化stylesheet
      •    2.2.1 准备
      •    2.2.2 stylesheet
      •    2.2.3 效果
    •   2.3 窗口大小调整与子控件自适应
  •   3.信号与槽
    •   3.1 简述
    •   3.2 信号与槽设置
      •    3.2.1 UI控件设置
      •    3.2.2 UI转到槽(自动连接)
      •    3.2.3 使用QObject::connect设置
      •    3.2.4 Lambda表达式设置
      •    3.2.5 使用函数指针
      •    3.2.6 自定义信号与槽
      •    3.2.7 自定义带参数信号与槽
  •   4.文件操作类
    •   4.1 介绍(所用)
    •   4.2 QFileDialog文件选择对话框
    •   4.3 文件读入操作
    •   4.4 文件保存操作
    •   4.5 文件关闭操作
    •   4.6 comboBox字符编码改变后操作
    •   4.7 设置行高亮显示行列号
    •   4.8 设置快捷方式创建和打开文件
    •   4.9 设置快捷方式放大缩小文字
  •   5.事件处理
    •   5.1 介绍
    •   5.2 事件处理(重写事件处理)
    •   5.3 鼠标滚轮实现textEdit文本字体放大缩小
    •   5.4 用事件自定义按键
      •    5.3.1 为自定义按键设置信号与槽
    •   5.5 将ui的textEdit控件提升为自定义MytextEdit
      •   5.6注:5.3QWidget与5.5将TextEdit提升为MyTextEdit事件处理的区别
  •   5.事件过滤(从事件过滤除修改而不改变事件处理方式)
    •   5.1 事件过滤器

 1.概述

  • 支持文本创建、打开、关闭、保存功能
  • 添加打开快捷键、添加保存快捷键
  • 底部显示行列号及文本字符 编码
  • ctrl+鼠标滚轮支持字体放大缩小

 2.界面

  2.1 界面布局

在这里插入图片描述

  2.2 UI美化stylesheet

   2.2.1 准备

  • 首先添加资源包
    在这里插入图片描述
  • 创建好后添加Prefix 前缀不要
    在这里插入图片描述
  • 添加文件并选择自己所需的文件
    在这里插入图片描述

   2.2.2 stylesheet

QPushButton { color: red }	//正常情况显示红色
QPushButton:hover { color: white }	//悬停后白色
QPushButton:pressed { color: black }	//按下后黑色

将其内容改为图片
1.选择按钮右键
2.选择样式表
3.点击添加资源旁倒三角,选择border-image
4.选择自己添加的图片资源,并将其自动生成的内容剪切到{}中
QPushButton { border-image: url(:/icon/o1.png); }
QPushButton:hover { border-image: url(:/icon/o2.png); }
QPushButton:pressed { border-image: url(:/icon/o3.png); }

   2.2.3 效果

在这里插入图片描述

  2.3 窗口大小调整与子控件自适应

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    //实现窗口大小调整与子控件自适应
    ui->setupUi(this);      //加载ui组件 this是Widget窗体的对象,ui是UI界面widget窗体的对象
    //虽然上面一行代码进行widget和ui窗口的关联,但如果窗口大小发生变化时,里面布局不会随之改变
    //通过下面这行代码进行显示说明,让窗口变化时,布局及其子控件随之调整
    this->setLayout(ui->verticalLayout);    //设置ui->verticalLayout与拉伸同步
    ui->widgetButtons->setLayout(ui->hlhorizontalLayout);   //设置ui->hlhorizontalLayout与拉伸同步
    ui->widgetButton->setLayout(ui->horizontalLayout);      //设置ui->horizontalLayout与拉伸同步
}

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

  3.信号与槽

  3.1 简述

1.信号(Signals):是由对象在特定事件发生时发出的消息。例如, QPushButton 有一个clicked() 信号,当用户点击按钮时发出。

2.(Slots):是用来响应信号的方法。一个槽可以是任何函数,当其关联的信号被发出时,该槽函数将被调用。

3连接信号和槽:使用 QObject::connect() 方法将信号连接到槽。当信号发出时,关联的槽函数会自动执行。

  3.2 信号与槽设置

   3.2.1 UI控件设置

在这里插入图片描述

发送者:btnClose---自己定义的名字:关闭按钮
信号:clicked() ---点击操作,点击发送信号
接受者:Widget ---- UI界面
槽: close()  ----- Widget执行槽函数close()进行关闭操作

流程:鼠标点击btnClose,btnClose发送clicked()信号,Widget接收到信号,执行槽函数close() 关闭Widget

   3.2.2 UI转到槽(自动连接)

当我们需要点击操作之后不是关闭而是要执行我们所需要的操作时,此时从UI控件点击右键转到槽
会自动生成一个槽函数,我们可以在生成的槽函数中写自己所需要的操作

在这里插入图片描述
在这里插入图片描述

在头文件中生成

在这里插入图片描述

在widget.cpp中生成

在这里插入图片描述

槽函数
void Widget::on_btnClose_clicked()
{
    qDebug() << " Close clicked";
}
此时点击关闭按钮会在运行程序输出栏中显示:Close clicked

在这里插入图片描述

   3.2.3 使用QObject::connect设置

最常用的方式,在构造函数中直接通过QObject::connect 函数连接信号和槽。
QObject::connect(sender,SIGNAL(signal()),receiver, SLOT(slot()));
根据3.2.1的设置相应的代码是
QObject::connect(ui->btnClose,SIGNAL(clicked()),this,SLOT(close()));
此种方法灵活多变,可将不同的发送者接入到同一种槽函数如:
QObject::connect(ui->btnOpen,SIGNAL(clicked()),this,SLOT(on_btnClose_clicked()));
将打开按键连接到已存在的槽函数on_btnClose_clicked()中。

若需要自定义新的槽函数,需在头文件中声明该函数,并自己写相应的槽函数。
在widget.h中自定义,然后再widget.cpp文件中添加自定义

在这里插入图片描述
在这里插入图片描述

   3.2.4 Lambda表达式设置

此种方式不需要如3.2.3一样声明槽函数,只需要在lambda函数体中进行操作即可,
注意的是第二位置不是用SIGNAL宏操作,而是用引用某个类里的函数
QObject::connect(sender,&Sender::signal, [=]() {/* lambda body */ });

在这里插入图片描述

将其函数体内改成某个槽函数也可
QObject::connect(ui->btnSave,&QPushButton::clicked,[=](){
	on_btnOpen_clickedMySelf();
});

   3.2.5 使用函数指针

QObject::connect(ui->btnOpen,&QPushButton::clicked,this,&Widget::on_btnOpen_clickedMySelf);

QObject::connect(ui->btnOpen,&QPushButton::clicked,this,&Widget::on_btnOpen_clickedMySelf);

   3.2.6 自定义信号与槽

在Qt中,自定义信号与槽是实现对象间通信的一种机制。信号和槽是Qt对象通信的核心特性,使得一个对象能够在发生某种事件时通知其他对象。自定义信号与槽的实现步骤如下:

1.定义信号:在Qt中,信号是由signals关键字声明的类成员函数。它们不需要实现,只需要声明

2.定义槽::槽可以是任何普通的成员函数,但通常在类定义中用 slots 关键字标识。槽可以有返回类型,也可以接受参数,但它们的参数类型需要与发出信号的参数类型匹配。

在widget.h文件中自定义信号与槽

在这里插入图片描述

3.连接信号与槽:使用 QObject::connect 函数将信号与槽连接起来。当信号被发射时,连接到这个信号的槽将被调用。

4.发射信号:使用 emit 关键字发射信号。当信号被发射时,所有连接到这个信号的槽都会被调用。

在这里插入图片描述

   3.2.7 自定义带参数信号与槽

过程与3.2.7一致,区别在于连接信号与槽时需要在括号内加入形参,且形参一致。

在这里插入图片描述
在这里插入图片描述

  4.文件操作类

  4.1 介绍(所用)

  • QFile
  • QTextStream
  • QFileDialog
  • QMessageBox
  • QTextCursor
  • QList
  • QTextEdit::ExtraSelection
  • QShortcut
  • QFont

  4.2 QFileDialog文件选择对话框

QString fileName = QFileDialog::getOpenFileName(this,tr("Open Text"), "C:/Users/qzh/Desktop", tr("Text (*.txt)"));
    /*
       tr("Open Text") 这个是设置对话框的标题是Open Text
       "C:/Users/qzh/Desktop"-打开的文件路径
       "Text (*.txt)" - 过滤的文件格式
                                            */

在这里插入图片描述
在这里插入图片描述

QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                        "C:/Users/qzh/Desktop",
                                                        tr("Text (*.txt *.doc)"));
                                                        
类似于4.1.1

  4.3 文件读入操作

在头文件中创建QFile实例对象用于判断其打开或关闭状态
在这里插入图片描述

/*
    点击打开按钮后操作的内容
    1.弹出选择打开的文件对话框
    2.创建一个所选的打开文件的对象实例
    3.设置文件可读可写的模式打开 并判断是否成功
    成功则:
    5.创建一个QTextStream对象的实例
    6.设置该实例的内容按comboBox显示的文本编码
    7.按行读取打开文本的内容
    8.追加写入ui控件TextEdit上并显示
*/

void Widget::on_btnOpen_clicked()
{
    /*
       tr("Open Text") 这个是设置对话框的标题是Open Text
       "C:/Users/qzh/Desktop"-打开的文件路径
       "Text (*.txt)" - 过滤的文件格式

        QFileDialog qFileDialog;
        qFileDialog.setFileMode(QFileDialog::AnyFile);
        qFileDialog.setNameFilter("*.txt");
        qFileDialog.exec();
        QStringList qstrings = qFileDialog.selectedFiles();
        for(QString str : qstrings){
            qDebug() << str;
        }   //过滤选择多个文件
                                            */
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open Text"), "C:/Users/qzh/Desktop", tr("Text (*.txt)"));

    file.setFileName(fileName);

    if(file.open(QIODevice::ReadWrite | QIODevice::Text)){
        ui->textEdit->clear();
        QTextStream in(&file);  //创建一个QTextStream对象的实例

        //ui->comboBox->currentText().toStdString().c_str();    将QString类型转化为Char * 型

        in.setCodec(ui->comboBox->currentText().toStdString().c_str()); //修改字符编码


        while(!in.atEnd()){
            QString context = in.readLine(); //对打开的文件按行读取
            //ui->textEdit->setText(context); //复写文本,会将已存文本覆盖
            ui->textEdit->append(context);   //对textEdit控件进行追加添加打开文件的内容
        }
    }   //以可读可写的方式打开,同时以Text文本的方式打开
}

  4.4 文件保存操作

/*
    保存按钮按下后
    1.判断文件是否打开
    若未被打开--文件是否存在
    2.弹出保存对话框并选择路径
    3.打开选择路径的文件
    若已打开
    4.实例化QTextStream对象
    5.设置该对象字符编码
    6.获取ui中TextEdit控件中的内容
    7.将获取的内容写入文实例化的对象中
*/
void Widget::on_btnSave_clicked()
{
    //1.判断文件是否打开
    if(!file.isOpen()){
        QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                                                        "C:/Users/qzh/Desktop",
                                                        tr("Text (*.txt *.doc)"));
        file.setFileName(fileName);
        if(!file.open(QFile::WriteOnly | QFile::Truncate)){
            qDebug() << "Open Error";
        };
    }
    QTextStream out(&file); //实例化对象
    out.setCodec(ui->comboBox->currentText().toStdString().c_str());    //设置字符编码
    QString context = ui->textEdit->toPlainText();  //以纯文本的形式返回文本编辑文本
    out << context;
}

  4.5 文件关闭操作

void Widget::on_btnClose_clicked()
{

    int ret = QMessageBox::warning(this, tr("My Application"),
                                    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:
          on_btnOpen_clicked();
          break;
      case QMessageBox::Discard:
          ui->textEdit->clear();
          if(file.isOpen()){
              file.close();
          }
          break;
      case QMessageBox::Cancel:
          // Cancel was clicked
          break;
      default:
          // should never be reached
          break;
    }
}

在这里插入图片描述

  4.6 comboBox字符编码改变后操作

首先将comboBox文本内容改变信号与自定义槽onCurrentTextChanged()连接


connect(ui->comboBox,SIGNAL(currentTextChanged(QString)),this,SLOT(onCurrentTextChanged()));
/*
    comboBox内字符编码改变后
    1.清空当前ui控件textEdit文本框内容
    2.判断文件是否打开
    3.若打开则实例化QTextStream对象
    4.设置字符编码
    5.将光标移动重新读取文件内容并写入ui的textEdit控件中
*/
void Widget::onCurrentTextChanged()
{
    ui->textEdit->clear();
    if(file.isOpen()){
        QTextStream in(&file);
        in.setCodec(ui->comboBox->currentText().toStdString().c_str());
        in.seek(0); // 移动光标至开头
        while(!in.atEnd()){
            QString context = in.readLine();
            //qDebug() << context;
            //ui->textEdit->setText(context); //复写
            ui->textEdit->append(context);    //追加
        }
    }
}

  4.7 设置行高亮显示行列号

设置行高亮函数:
void QTextEdit::setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections)

void Widget::onCursorPositionChanged()
{
    QTextCursor cursor = ui->textEdit->textCursor();
    /*
        cursor.blockNumber();   //返回行号 int 型
        cursor.columnNumber();  //返回列号 int 型
        QString::number();      //将数值型强制转成QString型
    */
    QString row = QString::number(cursor.blockNumber() + 1);
    QString col = QString::number(cursor.columnNumber() + 1);
    QString LabelMes = "行:" + row + ",列:" + col;
    ui->label->setText(LabelMes);

    //设置当前行高亮
    QList<QTextEdit::ExtraSelection> extraSelection;    //对extraSelection集合进行设置
    QTextEdit::ExtraSelection ext;  // QTextEdit::ExtraSelection成员cursor format
    //1.知道当前行
    ext.cursor = ui->textEdit->textCursor();

    //2.颜色
    QBrush qBrush(Qt::yellow);
    //void QTextFormat::setBackground(const QBrush &brush)
    ext.format.setBackground(qBrush);   //设置背景色
    ext.format.setProperty(QTextFormat::FullWidthSelection,true);   //设置属性整行选择
    //3.设置
    extraSelection.append(ext); //将ext加到extraSelection中
    ui->textEdit->setExtraSelections(extraSelection);
}

  4.8 设置快捷方式创建和打开文件

使用QShortcut
shortcut = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),
                          parent);

    QShortcut *shortcutOpen = new QShortcut(QKeySequence(tr("Ctrl+n", "File|Open")),
                                          this);
    QShortcut *shortcutSave = new QShortcut(QKeySequence(tr("Ctrl+s", "File|Open")),
                                          this);
    connect(shortcutOpen,&QShortcut::activated,[=](){
        on_btnOpen_clicked();
    });	//使用匿名函数信号由QShortcut::activated()发送

    connect(shortcutSave,&QShortcut::activated,[=](){
        on_btnSave_clicked();
    });

  4.9 设置快捷方式放大缩小文字

void setFont(const QFont &)

    QShortcut *shortcutZoomIn = new QShortcut(QKeySequence(tr("Ctrl+Shift+=", "File|Open")),
                                              this);

    QShortcut *shortcutZoomOut = new QShortcut(QKeySequence(tr("Ctrl+Shift+-", "File|Open")),
                                               this);

    connect(shortcutZoomIn,&QShortcut::activated,[=](){
        ZoomIn();
    });

    connect(shortcutZoomOut,&QShortcut::activated,[=](){
        ZoomOut();
    });

void Widget::ZoomIn()
{
    //获取textEdit字体信息
    QFont font = ui->textEdit->font();
    //获取当前文字的大小
    int currentSize = font.pointSize();
    if(currentSize == -1){
        return;
    }
    //改变字体的大小并设置
    int newSize = currentSize + 1;
    font.setPointSize(newSize);
    ui->textEdit->setFont(font);
}
void Widget::ZoomOut()
{
    //获取textEdit字体信息
    QFont font = ui->textEdit->font();
    //获取当前文字的大小
    int currentSize = font.pointSize();
    if(currentSize == -1){
        return;
    }
    //改变字体的大小并设置
    int newSize = currentSize - 1;
    font.setPointSize(newSize);
    ui->textEdit->setFont(font);
}


  5.事件处理

  5.1 介绍

  • 事件派发
  • 事件过滤
  • 事件分发
  • 事件处理
	众所周知Qt是一个基于C++的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。
我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率
才是最高的)。所以在Qt框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后事件会

	经过: 事件派发 -> 事件过滤->事件分发->事件处理几个阶段。
	
	Qt窗口中对于产生的一系列事件都有默认的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作,比如信号与槽就是一种事件(event)是由系统或者 Qt 本身在不同的场景下发出的。当用户按下/移动鼠标、敲下键盘,或者是窗口关闭/大小发生变化/隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,
如鼠标/键盘事件等;另一些事件则是由系统自动发出,如计时器事件。
	每一个Qt应用程序都对应一个唯一的 QApplication 应用程序对象,然后调用这个对象的 exec() 函数,这样Qt框架内部的事件检测就开始了( 程序将进入事件循环来监听应用程序的事件 )。

  5.2 事件处理(重写事件处理)

	在事件的四个步骤中,当我们需要对事件的处理结果进行操作时,只需要重写事件处理函数,在头文件中重写事件处理,重写enterEvent事件,
	过程:
	1.当鼠标进入事件产生后,qt使用应用程序调用notify()函数将事件发送到指定窗口
	2.在发送过程中可通过事件过滤器过滤,默认不过滤
	3.事件发送到指定窗口后,窗口的事件分发器会对收到的事件进行分类
	4.分类之后的事件(如鼠标事件,键盘事件)分发给对应的函数进行处理
	

在这里插入图片描述
在这里插入图片描述

  5.3 鼠标滚轮实现textEdit文本字体放大缩小

1.当ctrl按下后,事件产生
2.过滤事件默认不过滤
3.鼠标按下事件被分发
4.事件分发给keyPresseEvent函数(重写的)进行处理
5.将keyFlag标志为人为置1

void Widget::keyPressEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control){
        KeyFlag = 1;
    };
}

void Widget::keyReleaseEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control){
        KeyFlag = 0;
    };
}

void Widget::wheelEvent(QWheelEvent *e)
{
    if(KeyFlag == 1){
        if(e->angleDelta().y() > 0){    //返回滚轮的y轴数值
            ZoomIn();
        }else{
            ZoomOut();
        }
        e->accept();
    }
}

  5.4 用事件自定义按键

	1.首先自定义一个类Mybutton,继承于QWidget
	2.对相应的事件进行重写
	3.将widget控件提升为Mybutton,提升后其类为Mybutton

	绘图时:
	使用QPainter,先加载图片然后更新,触发painterEvent事件
	具体代码如下

在这里插入图片描述
在这里插入图片描述

#include "mybutton.h"

#include <QPainter>

Mybutton::Mybutton(QWidget *parent) : QWidget(parent)
{
    //load(const QString &fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor)
    //c++ 的好处调用函数形参列表可以不用传完可以帮助我们进行默认的填充
    pic.load(":/icon/o1.png");  //加载图片
    setFixedSize(pic.size());   //设置图片的大小
    update();
    
}

void Mybutton::mousePressEvent(QMouseEvent *event)
{
    pic.load(":/icon/o3.png");  //加载图片
    update();
}

void Mybutton::leaveEvent(QEvent *event)
{
    pic.load(":/icon/o1.png");  //加载图片
    update();
}

void Mybutton::enterEvent(QEvent *event)
{
    pic.load(":/icon/o2.png");  //加载图片
    update();
}

void Mybutton::paintEvent(QPaintEvent *event)   //paintEvent 当updata的时候才会刷新
{
    QPainter painter(this);
    painter.drawPixmap(rect(),pic);
    //rect() 获取当前绘画的矩形区域
}

   5.3.1 为自定义按键设置信号与槽

	1.首先为自定义信号自定义一个信号和槽,在Mybutton.h中添加clicked()信号,
	2.然后在widget.cpp中进行信号与槽的连接connect
	3.在鼠标按下事件中人为的发送自定义信号clicked -- emit clicked();

在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d7928229f95d4cf1b90a9053e7b75f5f.pn

  5.5 将ui的textEdit控件提升为自定义MytextEdit

	1.首先创建一个类,继承于QTextEdit
	2.将自定义MytextEdit与整个控件相关联
	3.重写事件
	4.将重写事件返回其正常状态

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include "mytextedit.h"
#include <QWheelEvent>


MyTextEdit::MyTextEdit(QWidget *parent) : QTextEdit(parent) //初始化列表构造函数进行与ui控件的关联
{

}

void MyTextEdit::wheelEvent(QWheelEvent *e)
{
    if(CtrlKeyPressFlag == 1){
        if(e->angleDelta().y() > 0){    //返回滚轮的y轴数值
            zoomIn();
        }else{
            zoomOut();
        }
        e->accept();
    }else{
        QTextEdit::wheelEvent(e);   //对wheelEvent重写后使其返回正常状态
    }
}

void MyTextEdit::keyPressEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control){
        CtrlKeyPressFlag = 1;
    };
    QTextEdit::keyPressEvent(e);    //对keyPressEvent重写后使其返回正常状态
}
void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
{
    if(e->key() == Qt::Key_Control){
        CtrlKeyPressFlag = 0;
    };
    QTextEdit::keyReleaseEvent(e);  //对keyReleaseEvent重写后使其返回正常状态
}

  5.6注:5.3QWidget与5.5将TextEdit提升为MyTextEdit事件处理的区别

	在QWidget中事件为virtual虚函数,对其重写并不影像其子类
	
	在QTextEdit中其继承于QWidget,
	其虚函数有其自己的内容,重写QTextEdit中的虚函数需要使其复原,
	因此在MyQTextEdit中重写其虚函数后需使MyQTextEdit重写的虚构函数复原返回其原本的功能	
	
	即当对某一控件事件进行自定义重写时,当重写完自己的需求后需将其原本的功能复原。

  5.事件过滤(从事件过滤除修改而不改变事件处理方式)

  5.1 事件过滤器

1.定义事件过滤器
2.安装事件过滤器
3.事件过滤器逻辑
4.事件分发
5.决定是否传递事件
5.目标对象处理事件
事件过滤器设置
1.声明
bool eventFilter(QObject *watched, QEvent *event);//公有

2.安装事件过滤器
 ui->textEdit->installEventFilter(this); //为textEdit安装事件过滤器,窗口的事件过滤器安装到textEdit上

3.编写事件过滤器
/*
    当ctrl和滚轮事件同时发生时返回true
    否则返回false
*/
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    /* //Qt::ControlModifier
    QKeyEvent *keyEvent = (QKeyEvent *)event;

    if(keyEvent->key() == Qt::Key_Control){
        qDebug() << "ctrl";
    }
    */
    //event是单一事件,只能检测一种
    //因此若想要按键按下和滚轮滚动同事被检测需要用两种不同的方式
    //QGuiApplication::keyboardModifiers() == Qt::ControlModifier   //事件过滤keyboard事件

    if(QGuiApplication::keyboardModifiers() == Qt::ControlModifier){    //ctrl被按下事件
        if(event->type() == QEvent::Wheel){ //滚轮事件
            qDebug() << "ctrl+wheel";

            //QEvent事件中没有angleDelta,所以将QEvent事件强制转换成QWeelEvent事件
            QWheelEvent *wheelEvent = dynamic_cast<QWheelEvent *>(event);//QWheelEvent *wheelEvent = (QWheelEvent *)event; //强制转换

            if(wheelEvent->angleDelta().y() > 0){
                ZoomIn();
            }else if(wheelEvent->angleDelta().y()<0){
                ZoomOut();
            }
            return true;
        }
        return false;
    }
}

链接:https://pan.baidu.com/s/15ZfAfkYXAnDl6kOMPSy6YA 
提取码:v23d 
--来自百度网盘超级会员V5的分享

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go 源码之 gin 框架

Go 源码之 gin 框架 go源码之gin - Jxy 博客 一、总结 gin.New()初始化一个实例&#xff1a;gin.engine&#xff0c;该实例实现了http.Handler接口。实现了ServeHTTP方法 注册路由、注册中间件&#xff0c;调用addRoute将路由和中间件注册到 methodTree 前缀树&#xff08;节…

flutter官方案例context_menus

1&#xff1a;根据项目中的案例进行部署 2&#xff1a;运行查看有什么用&#xff0c;可不可以直接复制粘贴 案例地址 https://github.com/flutter/samples/tree/main/context_menus案例展示方法 直接把这个文件夹中的文件复制到lib文件夹中 3&#xff0c;19&#xff0c;4的fl…

关系型数据库mysql(10)MHA的高可用

一. MHA 的相关知识 1. 什么是 MHA MHA&#xff08;MasterHigh Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。MHA 的出现就是解决MySQL 单点的问题。MySQL故障切换过程中&#xff0c;MHA能做到0-30秒内自动完成故障切换操作。MHA能在故障…

[Windows]防火墙,出入站规则失效。

场景&#xff1a; 因为具体需要&#xff0c;在内网中&#xff0c;不想别人发现我们的nacos端口8848&#xff0c;因此我们设置了入站规则&#xff0c;特定的ip地址才能访问。但是实际测试中发现并不起作用。。。 经过一番排查得到一下结果。 为什么有些应用绕过了防火墙配置 有…

JimuReport积木报表 v1.7.4 公测版本发布,免费的JAVA报表工具

项目介绍 一款免费的数据可视化报表&#xff0c;含报表和大屏设计&#xff0c;像搭建积木一样在线设计报表&#xff01;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; Web 版报表设计器&#xff0c;类似于excel操作风格&#xff0c;通过拖拽完成报…

Linux速览(2)——环境基础开发工具篇(其一)

本章我们来介绍一些linux的常用工具 目录 一. Linux 软件包管理器 yum 1.什么是软件包? 2. 查看软件包 3. 如何安装软件 4. 如何卸载软件 5.yum补充 6. 关于 rzsz 二. Linux编辑器-vim使用 1. vim的基本概念 2. vim的基本操作 3. vim正常模式命令集 4. vim末行模式…

计算机网络-从输入网址到访问网站的全过程

当我们在浏览器中输入一个网址并按下回车键时&#xff0c;会发生一系列复杂的过程&#xff0c;最终使我们能够看到网页的内容。以下是这个过程的详细步骤&#xff1a; 客户端&#xff1a;首先&#xff0c;用户在浏览器中键入网址&#xff0c;然后浏览器会根据这个网址生成一个H…

vultr ubuntu 服务器远程桌面安装及连接

一. 概述 vultr 上开启一个linux服务器&#xff0c;都是以终端形式给出的&#xff0c;默认不带 ui 桌面的&#xff0c;那其实对于想使用服务器上浏览器时的情形不是很好。那有没有方法在远程服务器安装桌面&#xff0c;然后原程使用呢&#xff1f;至少ubuntu的服务器是有的&am…

C练习题(1)

变种水仙花&#xff08;来自牛课网&#xff09; 题目 变种水仙花数 - Lily Number&#xff1a;把任意的数字&#xff0c;从中间拆分成两个数字&#xff0c;比如1461 可以拆分成&#xff08;1和461&#xff09;,&#xff08;14和61&#xff09;,&#xff08;146和1),如果所有拆…

IDEA 如何快速创建 Springboot 项目,面试题kafka数据丢失问题

&#xff08;3&#xff09;填写并选择&#xff1a; 1&#xff0c;2 处&#xff1a;是 Maven 工程的两个属性唯一标识&#xff0c;随意填。 3处&#xff1a;类型选择 Maven 项目 4处&#xff1a;语言选择 Java 5处&#xff1a;打包方式选择 Jar 6处&#xff1a;Java版本选择…

KeepAlived使用介绍

目录 1、Introduce 2、基本使用 &#xff08;1&#xff09;安装 &#xff08;2&#xff09;配置文件 &#xff08;3&#xff09;使用教程 1、Introduce keepalived是一个用于实现高可用性和负载均衡的开源软件。它提供了一种轻量级的方式来管理多个服务器&#xff0c;并确保…

【Spring Boot 源码学习】ConditionEvaluationReport 日志记录上下文初始化器

《Spring Boot 源码学习系列》 ConditionEvaluationReport 日志记录上下文初始化器 一、引言二、往期内容三、主要内容3.1 源码初识3.2 ConditionEvaluationReport 监听器3.3 onApplicationEvent 方法3.4 条件评估报告的打印展示 四、总结 一、引言 上篇博文《共享 MetadataRe…

【嵌入式智能产品开发实战】(十二)—— 政安晨:通过ARM-Linux掌握基本技能【运行环境】

目录 简述 开始 操作系统环境下的程序运行 裸机环境下的程序运行 程序入口main()函数分析 BSS段的小提示 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 嵌入式智能产品开发实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不…

Python 后端 Flask 使用 Flask-SocketIO、前端 Vue3 实现长连接 Websocket 通信详细教程(更新中)

Flask 安装 Flask-Socketio Flask-SocketIO 第三方库使 Flask 应用程序可以实现客户端和服务器之间的低延迟双向通信。客户端应用程序可以使用 Javascript、Python、C、Java 和 Swift 中的任何 SocketIO 客户端库或任何其他兼容客户端来建立与服务器的永久连接。 Flask-Socke…

施耐德 PLC 控制系统 产品 + 软件总体介绍 2020

参考 2020.7 官方说明视频&#xff1a;https://www.bilibili.com/video/BV1Mi4y1G7Qc/ 总体说明 施耐德作为工业控制界巨头&#xff08;公认的几大巨头&#xff1a;西门子、AB、施耐德&#xff09;&#xff0c;PLC 控制器产品线很庞大&#xff0c;涵盖了高中低的完整产品线&…

代码随想录Day24:回溯算法Part1

回溯算法理论&#xff1a; Leetcode 77. 组合 这道题其实有点绕的我头晕&#xff0c;对于start index的解释我能够理解&#xff0c;但是我很难去想清楚他是如何在一次次递归中变化的因为他在for循环外面扮演我们每一次在一个数字找完了他开头的所有组合之后&#xff0c;就把st…

永磁同步电机PMSM和直流无刷电机BLDCM整理

刚完成的永磁同步电机的助力转向项目&#xff0c;接下来又遇到一个直流无刷电机的项目。刚好有时间将两个电机控制的异同和经典的控制方案总结一下。首先解释一下PMSW和BLDCM的含义。PMSW(Permanent Magnet Synchronous Motor)永磁同步电机的缩写&#xff1b;BLDCM(BrushLess D…

Datacom HCIP笔记-OSPF协议 之三

从骨干区域传来的三类LSA不再传回骨干区域 VLINK 1、只要创建的VLINK的路由器都是ABR 2、VLINK永远属于区域0的链路。 3、VLINK只能在非骨干区域创建&#xff0c;只能跨越一个非骨干区域。 4、特殊区域不能创建VLINK 5、用于修复不连续的骨干区域 6、将非骨干区域和骨干区域直接…

财务管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目持续更新中..... 2024年计算机毕业论文&#xff08;设计&#xff09;学生选题参考合集推荐收藏&#xff08;包含Springboot、jsp、ssmvue等技术项目合集&#xff09; 目录 1. …

GridLayoutManager 中的一些坑

前言 如果GridLayoutManager使用item的布局都是wrap_cotent 那么会在布局更改时会出现一些出人意料的情况。&#xff08;本文完全不具备可读性和说教性&#xff0c;仅为博主方便查找问题&#xff09; 布局item: <!--layout_item.xml--> <?xml version"1.0&qu…