Qt——升级系列(Level Seven):事件、文件

news2024/11/23 2:54:32

目录

Qt事件

  事件介绍

  事件的处理

  按键事件

  鼠标事件

  定时器

  事件分发器

  事件过滤器

Qt文件

  Qt文件概述

  输入输出设备类

  文件读写类

  文件和目录信息类


Qt事件

  事件介绍

        事件是应⽤程序内部或者外部产⽣的事情或者动作的统称。在 Qt 中使⽤⼀个对象来表⽰⼀个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本⾝在不同的时刻发出的。当⽤⼾按下⿏标、敲下键盘,或者是窗⼝需要重新绘制的时候,都会发出⼀个相应的事件。⼀些事件是在⽤⼾操作时发出,如键盘事件、⿏标事件等,另⼀些事件则是由系统本⾝⾃动发出,如定时器事件。

常⻅的 Qt 事件如下:

常⻅事件描述: 

事件名称
描述
⿏标事件
⿏标左键、⿏标右键、⿏标滚轮,⿏标的移动,⿏标按键的按下和松开
键盘事件
按键类型、按键按下、按键松开
定时器事件
定时时间到达
进⼊离开事件
⿏标的进⼊和离开
滚轮事件
⿏标滚轮滚动
绘屏事件
重绘屏幕的某些部分
显⽰隐藏事件
窗⼝的显⽰和隐藏
移动事件
窗⼝位置的变化
窗⼝事件
是否为当前窗⼝
⼤⼩改变事件
窗⼝⼤⼩改变
焦点事件
键盘焦点移动
拖拽事件
⽤⿏标进⾏拖拽

  事件的处理

        事件处理⼀般常⽤的⽅法为:重写相关的 Event 函数。

        在 Qt 中,⼏乎所有的 Event 函数都是虚函数,所以可以重新实现。如:在实现⿏标的进⼊和离开事件时,直接重新实现 enterEvent() 和 leaveEvent() 即可。

enterEvent() 和 leaveEvent() 函数原型如下:

  按键事件

        Qt 中的按键事件是通过 QKeyEvent 类来实现的。当键盘上的按键被按下或者被释放时,键盘事件便会触发。在帮助⽂档中查找 QKeyEvent 类如下:

        查找按键事件中所有的按键类型:在帮助⽂档中输⼊:Qt::Key,如下图:  

        单个按键的例子

1、单个按键的按下事件: 

void MyWidget::keyPressEvent(QKeyEvent *event) 
{
    if (event->key() == Qt::Key_A) 
    {
        qDebug() << "按下了 A 键";
        // 执行相应的操作
    }
    QWidget::keyPressEvent(event);  // 传递事件给父类处理
}

2、单个按键的释放事件: 

void MyWidget::keyReleaseEvent(QKeyEvent *event) 
{
    if (event->key() == Qt::Key_A) 
    {
        qDebug() << "释放了 A 键";
        // 执行相应的操作
    }
    QWidget::keyReleaseEvent(event);  // 传递事件给父类处理
}

        组合按键的例子

1、同时按下多个键的事件:

void MyWidget::keyPressEvent(QKeyEvent *event) 
{
    if (event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_C) 
    {
        qDebug() << "同时按下了 Ctrl + C 键";
        // 执行相应的操作
    }
    QWidget::keyPressEvent(event);  // 传递事件给父类处理
}

 2、同时释放多个键的事件:

void MyWidget::keyReleaseEvent(QKeyEvent *event) 
{
    if (event->modifiers() & Qt::ShiftModifier && event->key() == Qt::Key_F) 
    {
        qDebug() << "同时释放了 Shift + F 键";
        // 执行相应的操作
    }
    QWidget::keyReleaseEvent(event);  // 传递事件给父类处理
}

在上述示例中:

  • keyPressEvent()keyReleaseEvent() 函数分别处理按键按下和释放事件。
  • 使用 QKeyEvent 对象的 key() 方法获取按下或释放的具体按键。
  • 使用 modifiers() 方法可以获取同时按下的修饰键(如 Ctrl、Shift 等)。
  • 在处理完事件后,通常会调用 QWidget::keyPressEvent(event)QWidget::keyReleaseEvent(event) 将事件传递给父类处理,以确保其他部分的事件处理逻辑能够正常运行。

  鼠标事件

        在 Qt 中,⿏标事件是⽤ QMouseEvent 类来实现的。当在窗⼝中按下⿏标或者移动⿏标时,都会产⽣⿏标事件。

        利⽤ QMouseEvent 类可以获取⿏标的哪个键被按下了以及⿏标的当前位置等信息。在 Qt 帮助⽂档中查找QMouseEvent类 如下图⽰:

        鼠标单击事件的例子

void MyWidget::mousePressEvent(QMouseEvent *event) 
{
    if (event->button() == Qt::LeftButton) 
    {
        qDebug() << "左键被按下";
        // 执行相应的操作
    } 
    else if (event->button() == Qt::RightButton) 
    {
        qDebug() << "右键被按下";
        // 执行相应的操作
    }
    QWidget::mousePressEvent(event);  // 传递事件给父类处理
}

        鼠标释放事件的例子

void MyWidget::mouseReleaseEvent(QMouseEvent *event) 
{
    if (event->button() == Qt::LeftButton) 
    {
        qDebug() << "左键被释放";
        // 执行相应的操作
    } 
    else if (event->button() == Qt::RightButton) 
    {
        qDebug() << "右键被释放";
        // 执行相应的操作
    }
    QWidget::mouseReleaseEvent(event);  // 传递事件给父类处理
}

        鼠标双击事件的例子

void MyWidget::mouseDoubleClickEvent(QMouseEvent *event) 
{
    if (event->button() == Qt::LeftButton) 
    {
        qDebug() << "左键双击";
        // 执行相应的操作
    } 
    else if (event->button() == Qt::RightButton) 
    {
        qDebug() << "右键双击";
        // 执行相应的操作
    }
    QWidget::mouseDoubleClickEvent(event);  // 传递事件给父类处理
}

        鼠标移动事件的例子

void MyWidget::mouseMoveEvent(QMouseEvent *event) 
{
    qDebug() << "鼠标移动到 (" << event->pos().x() << ", " << event->pos().y() << ")";
    // 执行相应的操作,例如更新鼠标位置的显示等
    QWidget::mouseMoveEvent(event);  // 传递事件给父类处理
}

        鼠标滚轮事件的例子 

void MyWidget::wheelEvent(QWheelEvent *event) 
{
    if (event->delta() > 0) 
    {
        qDebug() << "鼠标向上滚动";
        // 执行相应的操作
    } 
    else if (event->delta() < 0) 
    {
        qDebug() << "鼠标向下滚动";
        // 执行相应的操作
    }
    QWidget::wheelEvent(event);  // 传递事件给父类处理
}

  定时器

        Qt 中在进⾏窗⼝程序的处理过程中,经常要周期性的执⾏某些操作,或者制作⼀些动画效果,使⽤定时器就可以实现。所谓定时器就是在间隔⼀定时间后,去执⾏某⼀个任务。定时器在很多场景下都会使⽤到,如弹窗⾃动关闭之类的功能等。

Qt中的定时器分为 QTimerEvent 和 QTimer 这2个类。
        • QTimerEvent类 ⽤来描述⼀个定时器事件。在使⽤时需要通过 startTimer() 函数来开启⼀个定时器,这个函数需要输⼊⼀个以毫秒为单位的整数作为参数来表明设定的时间,它返回的整型值代表这个定时器。当定时器溢出时(即定时时间到达)就可以在 timerEvent() 函数中获取该定时器的编号来进⾏相关操作。
        • QTimer类 来实现⼀个定时器,它提供了更⾼层次的编程接⼝,如:可以使⽤信号和槽,还可以设置只运⾏⼀次的定时器。

QTimerEvent 类

        QTimerEvent类是用来描述定时器事件的类。它通常与 QObjecttimerEvent() 函数结合使用,用于处理定时器事件的回调操作。

使用方法:

  1. 启动定时器: 通过 startTimer() 函数启动一个定时器,该函数接受一个毫秒为单位的时间间隔作为参数,并返回一个整型值,代表该定时器的唯一标识符(定时器编号)。

  2. 定时器事件处理: 当定时器设定的时间间隔到达时,会触发 timerEvent() 函数。在 timerEvent() 函数中,可以通过传入的参数 QTimerEvent *event 来获取定时器的具体信息,例如定时器的标识符,从而执行相应的操作。

  3. 代码示例:

    void MyWidget::timerEvent(QTimerEvent *event) 
    {
        if (event->timerId() == timerId) 
        {
            qDebug() << "定时器事件触发,定时器ID:" << event->timerId();
            // 执行相应的定时操作
        }
        QWidget::timerEvent(event);  // 传递事件给父类处理
    }
    

QTimer 类

        QTimer类提供了更高级别的定时器功能,其主要特点是能够通过信号和槽机制来处理定时器事件,以及提供更多的灵活性和控制选项。

主要功能:

  1. 启动定时器: 通过 QTimerstart() 函数启动定时器,该函数接受一个毫秒为单位的时间间隔作为参数,还可以选择性地设置定时器的单次触发或重复触发。

  2. 定时器信号和槽: QTimer 可以通过信号 timeout() 来定期触发定时器事件。可以通过连接(connect)这个信号到槽函数来处理定时器事件,这使得定时器的使用更加方便和直观。

  3. 单次运行定时器: 可以使用 setSingleShot(true) 方法设置定时器为只运行一次,适用于需要在一段时间后执行一次任务的场景。

  4. 代码示例:

    // 创建一个 QTimer 对象
    QTimer *timer = new QTimer(this);
    
    // 设置定时器触发的时间间隔,单位为毫秒
    timer->setInterval(1000); // 1秒
    
    // 连接定时器的 timeout() 信号到槽函数
    connect(timer, &QTimer::timeout, [=]() 
    {
        qDebug() << "定时器触发";
        // 执行相应的定时操作
    });
    
    // 启动定时器
    timer->start();
    

区别和选择:

  • QTimerEvent 和 timerEvent(): 适合在自定义的 QObject 派生类中处理定时器事件,需要手动管理定时器的标识符和事件处理逻辑。

  • QTimer 类: 更高级别的接口,通过信号和槽机制处理定时器事件,适合在需要简单设置和操作定时器的场景下使用,无需手动管理定时器事件。

  事件分发器

        概述

        在 Qt 中,事件分发器(Event Dispatcher) 是⼀个核⼼概念,⽤于处理 GUI 应⽤程序中的事件。事件分发器负责将事件从⼀个对象传递到另⼀个对象,直到事件被处理或被取消。每个继承⾃ QObject类 或 QObject类 本⾝都可以在本类中重写 bool event(QEvent *e) 函数,来实现相关事件的捕获和拦截。

        事件分发器⼯作原理

        在 Qt 中,我们发送的事件都是传给了 QObject 对象,更具体点是传给了 QObject 对象的 event() 函数。所有的事件都会进⼊到这个函数⾥⾯,那么我们处理事件就要重写这个 event() 函数。event() 函数本⾝不会去处理事件,⽽是根据 事件类型(type值)调⽤不同的事件处理函数。事件分发器就是⼯作在应⽤程序向下分发事件的过程中,如下图:

        如上图,事件分发器⽤于分发事件。在此过程中,事件分发器也可以做拦截操作。事件分发器主要是通过 bool event(QEvent *e) 函数来实现。其返回值为布尔类型,若为 ture,代表拦截,不向下分发。

        Qt 中的事件是封装在 QEvent类 中,在 Qt 助⼿中输⼊ QEvent 可以查看其所包括的事件类型,如下图示:

        在Qt中声明和实现鼠标点击事件、事件分发器以及拦截事件时,通常会遵循以下步骤。下面是一个基本的示例,分别在头文件 widget.h 和实现文件 widget.cpp 中展示如何完成这些操作。

widget.h 头文件中声明

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMouseEvent>

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    // 声明鼠标点击事件处理函数
    void mousePressEvent(QMouseEvent *event) override;

    // 声明事件分发器函数
    bool event(QEvent *event) override;

private:
    // 声明拦截事件处理函数
    bool eventFilter(QObject *watched, QEvent *event) override;
};

#endif // WIDGET_H

widget.cpp 实现文件中实现

#include "widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent) : QWidget(parent)
{
    // 安装事件过滤器,用于拦截事件
    this->installEventFilter(this);
}

Widget::~Widget()
{
}

// 实现鼠标点击事件处理函数
void Widget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) 
    {
        qDebug() << "左键点击,位置:" << event->pos();
        // 执行相应的操作
    } 
    else if (event->button() == Qt::RightButton) 
    {
        qDebug() << "右键点击,位置:" << event->pos();
        // 执行相应的操作
    }

    // 将事件传递给父类处理
    QWidget::mousePressEvent(event);
}

// 实现事件分发器函数
bool Widget::event(QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress) 
    {
        // 处理鼠标按下事件
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        qDebug() << "事件分发器捕获到鼠标按下事件,位置:" << mouseEvent->pos();
        // 执行相应的操作
        return true; // 表示事件已处理
    }

    // 其他事件交给父类处理
    return QWidget::event(event);
}

// 实现事件过滤器函数
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == this && event->type() == QEvent::MouseMove) 
    {
        // 拦截并处理鼠标移动事件
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        qDebug() << "事件过滤器捕获到鼠标移动事件,位置:" << mouseEvent->pos();
        // 执行相应的操作
        return true; // 表示事件已处理
    }

    // 其他事件交给父类处理
    return QWidget::eventFilter(watched, event);
}

 代码说明:

  • mousePressEvent 函数: 在该函数中处理鼠标点击事件。根据 QMouseEventbutton() 方法判断是左键还是右键,并可以获取鼠标点击的位置信息。

  • event 函数: 这是事件分发器函数,用于捕获所有类型的事件。在示例中,通过判断事件的类型 (QEvent::MouseButtonPress) 来处理鼠标按下事件。

  • eventFilter 函数: 这是事件过滤器函数,通过调用 installEventFilter() 函数安装到对象上。在示例中,通过判断事件类型 (QEvent::MouseMove) 来处理鼠标移动事件。

  事件过滤器

        在 Qt 中,⼀个对象可能经常要查看或拦截另外⼀个对象的事件,如对话框想要拦截按键事件,不让别的组件接收到,或者修改按键的默认值等。通过上⾯的学习,我们已经知道,Qt 创建了 QEvent事件对象之后,会调⽤QObject 的 event()函数 处理事件的分发。显然,我们可以在 event()函数 中实现拦截的操作。由于 event()函数是 protected 的,因此,需要继承已有类。如果组件很多,就需要重写很多个event()函数。这当然相当⿇烦,更不⽤说重写 event()函数还得⼩⼼⼀堆问题。好在 Qt 提供了另外⼀种机制来达到这⼀⽬的:事件过滤器。

        事件过滤器是在应⽤程序分发到 event事件分发器 之前,再做⼀次更⾼级的拦截。如下图⽰:

事件过滤器的⼀般使⽤步骤:
    1、安装事件过滤器;
    2、重写事件过滤器函数:eventfilter() 。 

        假设我们有一个 MyWidget 类,它继承自 QWidget,并希望在该小部件上安装事件过滤器来拦截按键事件。以下是如何在 widget.cpp 中实现这个示例:

#include "widget.h"
#include <QDebug>
#include <QKeyEvent>

Widget::Widget(QWidget *parent) : QWidget(parent)
{
    // 创建一个 QLabel 作为被监视对象
    QLabel *label = new QLabel("监视对象", this);
    label->setGeometry(50, 50, 100, 30); // 设置标签的位置和大小

    // 安装事件过滤器到 label 上
    label->installEventFilter(this);
}

bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched->objectName() == "监视对象") 
    {
        if (event->type() == QEvent::KeyPress) 
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            qDebug() << "按键事件被拦截:按键" << keyEvent->key() << "被按下";
            
            // 在此处可以根据需求修改事件或者阻止事件继续传递
            // 例如,拦截所有按键事件,不让它传递给监视对象
            return true; // 返回 true 表示事件已处理
        }
    }

    // 其他事件交给父类处理
    return QWidget::eventFilter(watched, event);
}

示例说明:

  1. 安装事件过滤器:Widget 类的构造函数中,我们创建了一个 QLabel 对象作为被监视对象,并通过 installEventFilter() 函数将当前小部件 (this) 设置为其事件过滤器。

  2. 重写事件过滤器函数:eventFilter() 函数中,我们对事件进行检查和处理。在示例中,我们检查了被监视对象的对象名是否为 "监视对象",如果是,并且事件类型为 QEvent::KeyPress,则我们拦截并处理按键事件。在实际应用中,你可以根据需要修改事件内容、记录日志、阻止事件继续传递等操作。

  3. 返回值解释: 如果事件被处理了并且不需要传递给被监视对象,则返回 true;否则,返回 QWidget::eventFilter(watched, event),以继续将事件传递给父类处理。

Qt文件

  Qt文件概述

        ⽂件操作是应⽤程序必不可少的部分。Qt 作为⼀个通⽤开发库,提供了跨平台的⽂件操作能⼒。 Qt提供了很多关于⽂件的类,通过这些类能够对⽂件系统进⾏操作,如⽂件读写、⽂件信息获取、⽂件复制或重命名等。

  输入输出设备类

        在 Qt 中,⽂件读写的类为 QFile 。QFile 的⽗类为 QFileDevice ,QFileDevice 提供了⽂件交互操作的底层功能。 QFileDevice 的⽗类是 QIODevice,QIODevice 的⽗类为 QObject 。

        QIODevice 是 Qt 中所有输⼊输出设备(input/output device,简称 I/O 设备)的基础类,I/O 设备就是能进⾏数据输⼊和输出的设备,例如⽂件是⼀种 I/O 设备,⽹络通信中的 socket 是 I/O 设备, 串⼝、蓝⽛等通信接⼝也是 I/O 设备,所以它们也是从 QIODevice 继承来的。Qt 中主要的⼀些 I/O 设备类的继承关系如下图所⽰:

上图中各类的说明如下:
        • QFile 是⽤于⽂件操作和⽂件数据读写的类,使⽤ QFile 可以读写任意格式的⽂件。
        • QSaveFile 是⽤于安全保存⽂件的类。使⽤ QSaveFile 保存⽂件时,它会先把数据写⼊⼀个临时⽂件,成功提交后才将数据写⼊最终的⽂件。如果保存过程中出现错误,临时⽂件⾥的数据不会被写⼊最终⽂件,这样就能确保最终⽂件中不会丢失数据或被写⼊部分数据。 在保存⽐较⼤的⽂件或复杂格式的⽂件时可以使⽤这个类,例如从⽹络上下载⽂件等。
        • QTemporaryFile 是⽤于创建临时⽂件的类。使⽤函数 QTemporaryFile::open() 就能创建⼀个⽂件名唯⼀的临时⽂件,在 QTemporaryFile 对象被删除时,临时⽂件被⾃动删除。
        • QTcpSocket 和 QUdpSocket 是分别实现了 TCP 和 UDP 的类。
        • QSerialPort 是实现了串⼝通信的类,通过这个类可以实现计算机与串⼝设备的通信。
        • QBluetoothSocket 是⽤于蓝⽛通信的类。⼿机和平板计算机等移动设备有蓝⽛通信模块,笔记本电脑⼀般也有蓝⽛通信模块。通过QBluetoothSocket类,就可以编写蓝⽛通信程。如编程实现笔记本电脑与⼿机的蓝⽛通信。
        • QProcess 类⽤于启动外部程序,并且可以给程序传递参数。
        • QBuffer 以⼀个 QByteArray 对象作为数据缓冲区,将 QByteArray 对象当作⼀个 I/O 设备来读写。

  文件读写类

        在 Qt 中,⽂件的读写主要是通过 QFile 类来实现。在 QFile 类中提供了⼀些⽤来读写⽂件的⽅法。对于⽂件的操作主要有:
        • 读数据:QFile 类中提供了多个⽅法⽤于读取⽂件内容;如 read()、readAll()、readLine()等。
        • 写数据:QFile 类中提供了多个⽅法⽤于往⽂件中写内容;如 write()、writeData()等。
        • 关闭⽂件:⽂件使⽤结束后必须⽤函数 close() 关闭⽂件。

        访问⼀个设备之前,需要使⽤ open()函数 打开该设备,⽽且必须指定正确的打开模式,QIODevice 中所有的打开模式由 QIODevice::OpenMode 枚举变量定义,其取值如下:

QIODevice::NotOpen
没有打开设备
QIODevice::ReadOnly
以只读⽅式打开设备
QIODevice::WriteOnly
以只写⽅式打开设备
QIODevice::ReadWrite
以读写⽅式打开设备
QIODevice::Append
以追加⽅式打开设备,数据将写到⽂件末尾
QIODevice::Truncate
每次打开⽂件后重写⽂件内容,原内容将被删除
QIODevice::Text
在读⽂件时,⾏尾终⽌符会被转换为 '\n';当写⼊⽂件时,⾏尾终⽌符会被转换为 本地编码。如 Win32上为'\r\n';
QIODevice::Unbuffered
⽆缓冲形式打开⽂件,绕过设备中的任何缓冲区
QIODevice::NewOnly
⽂件存在则打开失败,不存在则创建⽂件

  文件和目录信息类

        QFileInfo 是 Qt 提供的⼀个⽤于获取⽂件和⽬录信息的类,如获取⽂件名、⽂件⼤⼩、⽂件修改⽇期等。QFileInfo类中提供了很多的⽅法,常⽤的有:
        • isDir() 检查该⽂件是否是⽬录;
        • isExecutable() 检查该⽂件是否是可执⾏⽂件;
        • fileName() 获得⽂件名;
        • completeBaseName() 获取完整的⽂件名;
        • suffix() 获取⽂件后缀名;
        • completeSuffix() 获取完整的⽂件后缀;
        • size() 获取⽂件⼤⼩;
        • isFile() 判断是否为⽂件;
        • fileTime() 获取⽂件创建时间、修改时间、最近访问时间等;

代码示例:

#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QFileInfo 对象,传入文件路径或者文件名
    QFileInfo fileInfo("/path/to/your/file.txt");

    // 获取文件名
    QString fileName = fileInfo.fileName();
    qDebug() << "文件名:" << fileName;

    // 获取文件路径
    QString filePath = fileInfo.filePath();
    qDebug() << "文件路径:" << filePath;

    // 获取文件大小(字节)
    qint64 fileSize = fileInfo.size(); // 返回 qint64 类型
    qDebug() << "文件大小:" << fileSize << "bytes";

    // 获取文件修改日期和时间
    QDateTime lastModified = fileInfo.lastModified();
    qDebug() << "最后修改时间:" << lastModified.toString(Qt::ISODate);

    // 获取文件后缀名
    QString suffix = fileInfo.suffix();
    qDebug() << "文件后缀名:" << suffix;

    // 检查文件是否存在
    if (fileInfo.exists()) 
    {
        qDebug() << "文件存在";
    } 
    else 
    {
        qDebug() << "文件不存在";
    }

    return a.exec();
}

 示例说明:

  1. 包含头文件: 引入了 QFileInfo 类的头文件 <QFileInfo>,以及用于调试输出的 <QDebug>

  2. 创建 QFileInfo 对象: 使用文件路径或文件名创建一个 QFileInfo 对象,例如 "/path/to/your/file.txt"

  3. 获取文件信息:

    • 使用 fileName() 获取文件名。
    • 使用 filePath() 获取文件路径。
    • 使用 size() 获取文件大小,返回 qint64 类型表示文件大小的字节数。
    • 使用 lastModified() 获取文件最后修改时间,返回 QDateTime 对象。
    • 使用 suffix() 获取文件后缀名。
  4. 检查文件存在性: 使用 exists() 函数检查文件是否存在,并根据结果输出相应信息。

  5. 输出信息: 使用 qDebug() 输出获取到的文件信息。

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

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

相关文章

Linux修炼之路之进程概念,fork函数,进程状态

目录 一&#xff1a;进程概念 二&#xff1a;Linux中的进程概念 三&#xff1a;用getpid(),getppid()获取该进程的PID,PPID 四&#xff1a;用fork()来创建子进程 五&#xff1a;操作系统学科的进程状态 六&#xff1a;Linux中的进程状态 接下来的日子会顺顺利利&#xf…

WordPress网站添加插件和主题时潜在危险分析

WordPress 最初只是一个简单的博客软件&#xff0c;现在据估计为全球前 1000 万个网站中的 30% 提供支持。WordPress受欢迎的因素之一是可以轻松创建插件和主题来扩展它并提供比默认设置更多的功能。 目前&#xff0c;WordPress 网站列出了 56,000 多个插件以及数千个主题。插件…

提升用户体验之requestAnimationFrame实现前端动画

requestAnimationFrame是什么 MDN官方解释 解析这段话&#xff1a; 1、那么浏览器重绘是指什么呢&#xff1f; ——大多数电脑的显示器刷新频率是60Hz&#xff0c;1000ms/6016.66666667ms的时间刷新一次 2、重绘之前调用指定的回调函数更新动画&#xff1f; ——requestAnima…

机器学习辅助的乙醇浓度检测

目录 1.为什么要机器学习 2. 神经网络一般组成 3.BP神经网络工作过程 4.评价指标 5.实操代码 1.为什么要用机器学习 人工分析大量的谐振模式&#xff0c;建立各种WGM的响应与未知目标之间的关系&#xff0c;是一个很大的挑战。机器学习(ML)能够自行识别全谱的全部特征。作为…

Python深度理解系列之【排序算法——冒泡排序】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️木道寻的主页 文章目录 &#x1f525;前言&#x1f680;冒泡排序python实现算法实现图形化算法展示 ⭐️⭐️⭐️总结 &#x1f525;前…

ONLYOFFICE8.1版本桌面编辑器简单测评

ONLYOFFICE官网链接&#xff1a;在线PDF查看器和转换器 | ONLYOFFICE ONLYOFFICE介绍&#xff1a;https://www.onlyoffice.com/zh/office-suite.aspx OnlyOffice 是一款免费且开源的 Office 协作办公套件&#xff0c;支持桌面端和移动端等多平台&#xff0c;由一家领先的 IT 公…

OpenStack开源虚拟化平台(二)

目录 三、对象存储服务Swift&#xff08;一&#xff09;Swift特性&#xff08;二&#xff09;应用场景&#xff08;三&#xff09;Swift主要组件&#xff08;四&#xff09;Swift基本原理&#xff08;五&#xff09;实例分析 四、镜像服务Glance&#xff08;一&#xff09;Glan…

如何在 Java 应用中使用 Jedis 客户端库来实现 Redis 缓存的基本操作

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

图解 Kafka 架构

写在前面 Kafka 是一个可横向扩展&#xff0c;高可靠的实时消息中间件&#xff0c;常用于服务解耦、流量削峰。 好像是 LinkedIn 团队开发的&#xff0c;后面捐赠给apache基金会了。 kafka 总体架构图 Producer&#xff1a;生产者&#xff0c;消息的产生者&#xff0c;是消息的…

不改代码,实现web.config或app.config的连接字符串加密解密

目的&#xff1a;加密字符串&#xff0c;防止明文显示。 好处&#xff1a;不用修改代码&#xff0c;微软自带功能&#xff0c;自动解密。 web.config 参考相关文章&#xff1a; Walkthrough: Encrypting Configuration Information Using Protected Configuration | Microso…

本地通过ollama下载模型,并使用python跑这个本地模型

1&#xff0c;这是ollama地址&#xff0c;下载对应的安装包 https://ollama.com/?viaurlainavpro.com 2&#xff0c;下载完直接安装即可&#xff0c;安装完后&#xff0c;winr打开cmd&#xff0c;出现这个&#xff0c;基本就妥了 3&#xff0c;这里我们需要去下载模型&#x…

笔记:Git学习之应用场景和使用经验

目标&#xff1a;整理Git工具的应用场景和使用经验 一、开发环境 Git是代码版本控制工具&#xff1b;Github是代码托管平台。 工具组合&#xff1a;VSCode Git 需要安装的软件&#xff1a;vscode、Git 其中vscode需要安装的插件&#xff1a;GitLens、Git History 二、应用…

【NLP学习笔记】load_dataset加载数据

除了常见的load_dataset(<hf上的dataset名>)这种方式加载HF上的所有数据外&#xff0c;还有其他custom的选项。 加载HF上部分数据 from datasets import load_dataset c4_subset load_dataset("allenai/c4", data_files"en/c4-train.0000*-of-01024.js…

PowerBi 获取指定时间间隔的日期的方法

获取指定时间间隔的日期&#xff0c;比如我们想得到2024年5月31日后的第三天。 网络上的教程一般是使用DATEADD()函数。 但是这个函数返回的是表。假如我们的需求是不做汇总等计算&#xff0c;只是把它作为一个计算列&#xff0c;或者度量值&#xff0c;那么我更推荐用DATE(&…

webstorm 高效查看不同分支差异 摒弃你的git diff手动操作

背景 每次代码冲突或者版本发生异常时&#xff0c;排查不同版本时就是一个头大的问题&#xff0c;头大的点在于用 vscode 的 git diff 一点点地排查和比较&#xff0c;耗时耗力&#xff0c;版面展不开&#xff0c;commit 差异看不出来&#xff0c;每个页面的代码不同也不能快速…

【Java08】方法(上)

从面向对象的角度来看&#xff0c;Java中的方法是类或对象行为的抽象。但和C不同&#xff0c;Java中”剔除“了C中”残留“的结构化编程。具体地说&#xff0c;Java中的方法必须在类中定义&#xff0c;没有独立存在的函数。 也有人把结构化编程&#xff0c;叫做”面向函数的编程…

Linux基础指令介绍与详解——原理学习

前言&#xff1a;本节内容标题虽然为指令&#xff0c;但是并不只是讲指令&#xff0c; 更多的是和指令相关的一些原理性的东西。 如果友友只想要查一查某个指令的用法&#xff0c; 很抱歉&#xff0c; 本节不是那种带有字典性质的文章。但是如果友友是想要来学习的&#xff0c;…

基于FPGA的DDS信号发生器

前言 此处仅为基于Vivado实现DDS信号发生器的仿真实现&#xff0c;Vivado的安装请看下面的文章&#xff0c;这里我只是安装了一个标准版本&#xff0c;只要能够仿真波形即可。 FPGA开发Vivado安装教程_vivado安装 csdn-CSDN博客 DDS原理 DDS技术是一种通过数字计算生成波形…

Linux shell编程学习笔记61: pstree 命令——显示进程树

0 前言 在 Linux shell编程学习笔记59&#xff1a; ps 获取系统进程信息&#xff0c;类似于Windows系统中的tasklist 命令https://blog.csdn.net/Purpleendurer/article/details/139696466?spm1001.2014.3001.5501 中我们研究了ps命令。在Linux中&#xff0c;通过ps命令&am…

William Yang:从区块链先锋到艺术平台创始人

在区块链技术和加密货币市场飞速发展的今天&#xff0c;William Yang无疑是这一领域的佼佼者。他不仅在学术和媒体领域取得了显著成就&#xff0c;更在创业之路上不断探索&#xff0c;成为了业内知名的KOL&#xff08;关键意见领袖&#xff09;。今天&#xff0c;我们有幸采访到…