QT从入门到实战x篇_22_番外1_Qt事件系统

文章目录

  • 1. Qt事件系统简介
    • 1.1 事件的来源和传递
    • 1.2 事件循环和事件分发
      • 1.2.1 QT消息/事件循环机制
        • 1.2.1.1 机制解释
        • 1.2.1.2 两个问题
      • 1.2.2 事件分发
  • 2. 事件过滤基础
    • 2.1 什么是事件过滤器(Event Filter)?
    • 2.2 如何安装事件过滤器
  • 3. 事件过滤实战
    • 3.1 创建自定义事件过滤器
    • 3.2 过滤不同类型的事件
    • 3.3 在多个对象之间共享事件过滤器
  • 4 高级应用
    • 4.1 使用事件过滤器实现拖放功能
    • 4.2 利用事件过滤器优化性能
  • 5 事件过滤的注意事项
    • 5.1 避免过度过滤
    • 5.2 确保事件的正确传递

比本篇好很多更多涉及底层的博文推荐: 【Qt 应用开发 】探索Qt事件处理时机:深入理解事件驱动机制

介绍清晰结构简洁的博文:Qt - QObject事件

以下部分来自:【Qt 元对象系统】深入探索Qt事件过滤:从基础到高级应用-CSDN博客、Qt事件系统:Qt中的事件处理与传递、Qt 事件机制、Qt之事件处理机制

1. Qt事件系统简介

在Qt中,事件(Event)是一个核心概念,它代表了应用程序的一个动作或发生的事情。事件可以是用户的输入,如鼠标点击或键盘按键,也可以是系统生成的,如窗口大小改变或定时器超时。

为了处理这些事件,Qt提供了一个事件循环(Event Loop)。这个循环不断地检查是否有新的事件发生,然后将这些事件发送给相应的对象进行处理。

事件(event)是由系统或者Qt本身在不同时刻发出的。当用户按下鼠标、敲下键盘,或者其它情况时候都会发出一个相应的事件。一些事件在对用户操作做出相应时发出,如键盘事件等;另外一些则是由系统自动发出,如计时事件等。

Qt程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始Qt的事件循环。在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件,当事件发生时,Qt将创建一个事件对象。Qt中所有事件类都继承自QEvent。在事件对象创建完毕之后,Qt将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是按照事件对象的类型分派给指定的事件处理函数(event handler)进行处理。

  • 事件和信号的区别

需要说明的是,事件与信号并不相同,比如单击一下界面上的按钮,那么就会产生鼠标事件 QMou­seEvent (不是按钮产生的 ),而因为按钮被按下了 ,所以它会发出 clicked() 单击信号(是按钮产生的)。这里一般只关心按钮的单击信号,而不用考虑鼠标事件,但是如果要设计一个按钮,或者当单击按钮时让它产生别的效果,那么就要关心鼠标事件了。可以看到,事件与信号是两个不同层面的东西,发出者不同,作用也不同。在 Qt 中,任何 QObject 子类实例都可以接收和处理事件。摘自:[Qt事件系统:Qt中的事件处理与传递_事件处理系统对于每个学习qt人来说非常重要,可以说,qt是以事件驱动的ui工具集。 大-CSDN博客](Qt事件系统:Qt中的事件处理与传递_件处理系统对于每个学习qt人来说非常重要,可以说,qt是以事件驱动的ui工具集。 大-CSDN博客)

Qt的事件很容易和信号槽混淆。signal由具体对象发出,然后会马上交给由connect函数连接的slot进行处理;

而对于事件,Qt使用一个事件队列对所有发出的事件进行维护,当新的事件产生时,会被追加到事件队列的尾部,前一个事件完成后,取出后面的事件接着再进行处理。

但是,必要的时候,Qt的事件也是可以不进入事件队列,而是直接处理的。并且,事件还可以使用“事件过滤器”进行过滤。

比如一个按钮对象, 我们使用这个按钮对象的时候, 我们只关心它被按下的信号, 至于这个按钮如何接收处理鼠标事件,再发射这个信号,我们是不用关心的。

但是如果我们要重载一个按钮的时候,我们就要面对event了。 比如我们可以改变它的行为,在鼠标按键按下的时候(mouse press event) 就触发clicked()的signal而不是通常在释放的( mouse release event)时候。

总结的说,Qt的事件和Qt中的signal不一样。 后者通常用来使用widget, 而前者用来实现widget。 如果我们使用系统预定义的控件,那我们关心的是信号,如果自定义控件我们关心的是事件。摘自:Qt 事件机制

  • 事件的处理
    一个事件由一个特定的 QEvent 子类来表示,但是有时一个事件又包含多个事件类型,比如鼠标事件又可以分为鼠标按下、双击和移动等多种操作。这些事件类型都由 QEvent 类的枚举型 QEvent::Type 来表示,其中包含了 一百多种事件类型,可以在 QEvent 类的帮助文档中查看。虽然 QEvent 的子类可以表示一个事件,但是却不能用来处理事件,那么应该怎样来处理一个事件呢?在 QCoreApplication 类的 notify() 函数的帮助文档处给出了 5 种处理事件的方法:

    • 方法一:重新实现部件的 paintEvent()、mousePressEvent() 等事件处理函数。这是最常用的一种方法,不过它只能用来处理特定部件的特定事件。
    • 方法二:重新实现 notify() 函数。这个函数功能强大,提供了完全的控制,可以在事件过滤器得到事件之前就获得它们。但是,它一次只能处理一个事件。
    • 方法三:向 QApplication 对象上安装事件过滤器。因为一个程序只有一个 QApplication 对象,所以这样实现的功能与使用 notify() 函数是相同的,优点是可以同时处理多个事件。
    • 方法四:重新实现 event() 函数。QObject 类的 event() 函数可以在事件到达默认的事件处理函数之前获得该事件。
    • 方法五:在对象上安装事件过滤器。使用事件过滤器可以在一个界面类中同时处理不同子部件的不同事件。

在实际编程中,最常用的是方法一,其次是方法五。因为方法二需要继承自 QApplication 类;而方法三要使用一个全局的事件过滤器,这将减缓事件的传递,所以,虽然这两种方法功能很强大,但是却很少被用到。

1.1 事件的来源和传递

在Qt中,事件可以由多种来源生成,包括用户输入、系统事件或自定义事件。一旦事件被生成,它会被发送到一个事件队列(Event Queue)。事件循环会从队列中取出事件,并将其传递给适当的对象进行处理

事件的传递是一个层层递进的过程。首先,事件会被发送到最顶层的对象,如应用程序对象(QApplication)。如果这个对象没有处理该事件,它会继续传递给下一级的对象,如窗口或控件,直到找到一个可以处理该事件的对象为止。

这种事件传递的方式,很像我们在生活中面对决策时的思考过程。当遇到一个问题时,我们首先会尝试自己解决,如果不能解决,我们可能会寻求他人的帮助,直到问题得到解决。

在每个程序的 main() 函数的最后都会调用 QApplication 类的 exec() 函数,它会使 Qt 应用程序进人事件循环,这样就可以使应用程序在运行时接收发生的各种事件。一旦有事件发生,Qt 便会构建一个相应的 QEvent 子类的对象来表示,然后将它传递给相应的 QObject 对象或其子对象。下面通过例子来看一下 Qt 中的事件传递过程。

新建 Qt Gui 应用,项目名称为 myEvent,基类选择 QWidget,然后类名保持 Widget 不变。建立完成后向项目中添加新文件,模板选择 C++ 类,类名为 MyLineEdit,基类手动填写为 QLineEdit,自定义了一个 MyLineEdit 类。

mylineEdit. h 文件:

#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H#include <QLineEdit>class MyLineEdit : public QLineEdit
{Q_OBJECT
public:explicit MyLineEdit(QWidget *parent = nullptr);// event()函数获取事件的类型bool event(QEvent *event);    protected:// MyLineEdit类的键盘按下事件void keyPressEvent(QKeyEvent *event);
};#endif // MYLINEEDIT_H

这里添加了 keyPressEvent() 函数和 event() 函数的声明。

mylineEdit. cpp 文件:

#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>MyLineEdit::MyLineEdit(QWidget *parent) :QLineEdit(parent)
{}// MyLineEdit类的键盘按下事件
void MyLineEdit::keyPressEvent(QKeyEvent *event)
{qDebug() << tr("MyLineEdit键盘按下事件");// 让MyLineEdit输入栏能输入字符QLineEdit::keyPressEvent(event);          // 执行QLineEdit类的默认事件处理event->ignore();                          // 忽略该事件
}//event()函数获取事件的类型
bool MyLineEdit::event(QEvent *event)  
{// 判断触发事件类型是否为键盘按下事件if(event->type() == QEvent::KeyPress)qDebug() << tr("MyLineEdit的event()函数");return QLineEdit::event(event);   // 执行QLineEdit类event()函数的默认操作
}

这里自定义了一个 MyLineEdit 类,它继承自 QWidget,并且实现了 MyLineEdit 类的 keyPressEvent() 函数和 event() 函数。event() 函数中使用了 event->type() 来获取事件的类型。如果是键盘按下事件 QEvent::KeyPress,则输出信息,另外返回父类的 event() 函数的操作结果。

widget.h 文件:

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
class MyLineEdit;
namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();// Widget类的事件过滤器bool eventFilter(QObject *obj, QEvent *event);    private:Ui::Widget *ui;MyLineEdit *lineEdit;protected:// Widget类的键盘按下事件void keyPressEvent(QKeyEvent *event);
};#endif // WIDGET_H

这里也添加了keyPressEvent()函数的声明。

widget.cpp 文件:

#include "widget.h"
#include "ui_widget.h"
#include "mylineedit.h"
#include <QKeyEvent>
#include <QDebug>Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);lineEdit = new MyLineEdit(this);lineEdit->move(100, 100);
}Widget::~Widget()
{delete ui;
}// Widget类的键盘按下事件
void Widget::keyPressEvent(QKeyEvent *event)
{qDebug() << tr("Widget键盘按下事件");
}// Widget类的事件过滤器
bool Widget::eventFilter(QObject *obj, QEvent *event) // 事件过滤器
{// 如果是lineEdit部件上的事件if(obj == lineEdit){              if(event->type() == QEvent::KeyPress)qDebug() << tr("Widget的事件过滤器");}return QWidget::eventFilter(obj, event);
}

这里也实现了 Widget 类的 keyPressEvent() 函数,并且会调用 MyLineEdit 类的 keyPressEvent() 函数。在事件过滤器中,先判断该事件的对象是不是 lineEdit,如果是,再判断事件类型,最后返回 QWidget 类默认的事件过滤器的执行结果。

运行程序,然后按下键盘的任意键,比如这里按下 a 键,执行结果如下图所示。
在这里插入图片描述

可以看到,事件的传递顺序是这样的:先是事件过滤器,然后是焦点部件的 event() 函数,最后是焦点部件的事件处理函数,例如这里的键盘按下事件函数;如果焦点部件忽略了该事件,那么会执行父部件的事件处理函数,如上图所示。注意,event() 函数和事件处理函数,是在该部件内进行重新定义的,而事件过滤器却是在该部件的父部件中进行定义的。
在这里插入图片描述

1.2 事件循环和事件分发

1.2.1 QT消息/事件循环机制

事件循环是Qt事件处理的核心。它不断地检查事件队列,看是否有新的事件需要处理。一旦有事件,事件循环会将其取出,并通过事件分发(Event Dispatching)将其发送给适当的对象。

Qt作为一个可视化GUI界面操作系统,是基于事件驱动的,我们程序执行的顺序不再是线性的,而是由一个个应用程序内部或外部的事件进行驱动的,无事件时便阻塞。这个有点类似于while循环,函数体内不断处理用户的输入,类比到事件循环中,用户点击了鼠标,按下了键盘,便称为事件。
  一般对于带UI窗口的程序来说,“事件”是由操作系统或程序框架在不同的时刻发出的。当用户按下鼠标,敲下键盘,或是窗口需要重新绘制的时候,或是计时器触发的时候,都会发出一个相应的事件。下面是一个抽象的“循环事件”的代码:

 1 function eventloop()2 {3     initialize();4     bool shouldQuit = false;5     whlie (false == shouldQuit)6     {7         var message = get_next_message();8         process_message(message);9         if (message == QUIT)
10         {
11             shouldQuit = true;
12         }
13     }
14 }
1.2.1.1 机制解释

这样的程序运行流程,叫做“事件驱动”式的程序。一般的Qt程序,main函数中都会有一个QCoreApplication/QGuiApplication/QApplication,并在末尾调用exec。Application中的这个EventLoop,叫做“事件循环”,所有的事件分发、事件处理都从这里开始。

Application还提供了sendEvent和poseEvent两个函数,分别用来发送事件。sendEvent发出的事件会立即被处理,即“同步”执行。poseEvent发送的事件会被加入事件队列,在下一轮事件循环时才处理,即“异步”执行。

1.2.1.2 两个问题

(1) Qt是事件驱动的,怎么理解这句话
  Qt将系统产生的信号(软件中断)转换成Qt事件,并且将事件封装成类,所有的事件类都是由QEvent派生的,事件的产生和处理就是Qt程序的主轴,且伴随整个程序的运行周期。因此说Qt是事件驱动的。

QT将系统产生的消息转化为QT事件,QT事件被封装为对象,所有的QT事件均继承抽象类QEvent,用于描述程序内部或外部发生的动作,任意的QObject对象都具备处理QT事件的能力。

在这里插入图片描述

(2) Qt事件由谁产生的?
  事件有两个来源:程序内部和程序外部,多数情况下来自操作系统并且通过spontaneous()函数返回true来获知事件来自程序外部,当spontaneous()函数返回false时说明事件来自程序内部。

####1.2.1.2 Qt事件处理流程

事件循环:事件是一个类对象,具有特定的类型,多数情况下是被分发到一个队列中(事件队列),当队列中有事件时就不停地将队列中的事件发送给QObject对象,当队列为空时,就阻塞地等待事件。

在这里插入图片描述

QCoreApplication::exec()开启了这种循环,一直到QCoreApplication::exit()被调用才终止,所以说事件循环是伴随着Qt程序的整个运行周期。
另外一种同步处理情形是通过sendEvent()将事件发送出去,直接进入事件的传送和处理流程。

在这里插入图片描述

1.2.2 事件分发

事件分发是事件循环的一个重要环节。当事件被取出后,它需要被分发到正确的对象进行处理。Qt提供了一个事件分发器(QEventDispatcher)来完成这个任务。事件分发器会根据事件的类型和目标对象,将事件发送到正确的处理函数中。

要理解事件分发的底层原理,我们需要深入Qt的源码。在Qt的源码中,QEventDispatcher类负责事件的分发。当一个事件被取出时,QEventDispatcher会首先检查该事件的类型,然后根据事件的类型,调用相应的处理函数。

例如,当一个鼠标点击事件被取出时,QEventDispatcher会调用mousePressEvent()函数进行处理。这确保了每种事件都能被正确处理。

事件类型处理函数
鼠标点击mousePressEvent()
键盘输入keyPressEvent()
窗口大小改变resizeEvent()

2. 事件过滤基础

在深入探讨Qt的事件过滤机制之前,我们首先要理解为什么我们会选择某种编程方式。人们在面对问题时,往往会寻找最直观、最简单的方法来解决。这与我们的大脑对于复杂性的处理方式有关。我们的大脑会自动寻找模式,并尝试将新的信息与已知的模式相匹配,以减少认知负担。

2.1 什么是事件过滤器(Event Filter)?

事件过滤器(Event Filter)是Qt事件处理系统中的一个核心组件。它允许开发者在事件被传递给目标对象之前,对其进行拦截和处理。这种机制为我们提供了一个强大的工具,使我们能够在不修改目标对象的代码的情况下,对其行为进行定制。

从底层源码的角度看,当一个事件被发送或者发布时,它首先会被传递给安装在目标对象上的事件过滤器。如果事件过滤器选择处理这个事件,那么这个事件就不会再被传递给目标对象。反之,如果事件过滤器选择忽略这个事件,那么这个事件会继续被传递给目标对象。

这种机制的存在,使我们能够更加灵活地处理事件,而不需要修改已有的代码。

2.2 如何安装事件过滤器

在Qt中,安装事件过滤器是一个简单的过程。首先,你需要创建一个继承自QObject的类,并重写其eventFilter(QObject *watched, QEvent *event)方法。然后,你可以使用QObject::installEventFilter(QObject *filterObj)方法,将你的事件过滤器安装到任何QObject派生的对象上。

从底层原理的角度看,当你安装一个事件过滤器时,Qt会将这个过滤器添加到目标对象的内部事件过滤器列表中。当一个事件被发送到这个对象时,Qt会按照事件过滤器列表中的顺序,依次调用每一个事件过滤器的eventFilter方法。

为了帮助读者更好地理解事件过滤器的工作原理,我们可以从以下几个角度进行总结和对比:

角度事件过滤器常规事件处理
灵活性
代码侵入性
性能开销低至中

3. 事件过滤实战

3.1 创建自定义事件过滤器

当我们想要对特定的事件进行处理或拦截时,自定义事件过滤器(Event Filter)成为了一个非常有力的工具。例如,当用户点击一个按钮(Button)时,我们可能想要在底层捕获这个点击事件并进行一些特殊的处理。

首先,我们需要创建一个继承自QObject的类,并重写其eventFilter(QObject *watched, QEvent *event)方法。在这个方法中,我们可以根据event的类型进行相应的处理。

bool CustomEventFilter::eventFilter(QObject *watched, QEvent *event) {if (event->type() == QEvent::MouseButtonPress) {// 处理鼠标点击事件}return QObject::eventFilter(watched, event);
}

在这里,我们可以看到事件过滤的真正力量。我们可以在事件到达目标对象之前捕获并处理它。这种能力使我们能够在底层进行细致的控制,而不仅仅是在高级API上进行操作。

3.2 过滤不同类型的事件

Qt提供了多种事件类型,例如QEvent::KeyPressQEvent::MouseMove等。每种事件类型都与特定的用户交互行为相关联。为了更好地理解这些事件类型,我们可以从以下几个角度进行对比:

事件类型(Event Type)触发条件(Trigger Condition)常见应用(Common Use Case)
QEvent::KeyPress键盘按键被按下快捷键处理
QEvent::MouseMove鼠标移动拖放操作
QEvent::MouseButtonPress鼠标按钮被按下自定义点击行为

3.3 在多个对象之间共享事件过滤器

有时,我们可能希望在多个对象之间共享同一个事件过滤器。这可以通过将事件过滤器安装到多个对象上来实现。这种方法的优势在于,我们可以在一个中心位置处理所有相关的事件,而不是分散在多个地方。

但是,这也带来了一个挑战:如何区分事件的来源?答案是使用watched参数,它指示产生事件的对象。

bool CustomEventFilter::eventFilter(QObject *watched, QEvent *event) {if (watched == button1 && event->type() == QEvent::MouseButtonPress) {// 处理button1的点击事件} else if (watched == button2 && event->type() == QEvent::MouseButtonPress) {// 处理button2的点击事件}return QObject::eventFilter(watched, event);
}

在这里,我们使用了watched参数来确定事件的来源,并据此进行相应的处理。

当我们调用installEventFilter方法时,Qt内部会将事件过滤器添加到一个列表中。每当一个事件被分发到对象时,Qt都会首先检查这个对象是否有安装的事件过滤器。如果有,它会按照安装的顺序调用这些事件过滤器。

这种机制确保了事件过滤器总是在事件到达目标对象之前被调用,从而使我们能够在事件到达目标之前进行拦截或处理。

4 高级应用

4.1 使用事件过滤器实现拖放功能

拖放功能(Drag and Drop)是许多应用程序中常见的交互方式。在Qt中,实现这一功能需要对QDrag和QDropEvent有深入的了解。但为什么我们会选择拖放作为交互方式呢?这与人们对直观和简单的追求有关。拖放为用户提供了一种直观的方式来操作对象,而不需要通过复杂的命令或菜单。

从底层源码的角度看,当我们开始拖动一个对象时,QDrag对象会被创建,并开始监听鼠标的移动事件。当对象被放下时,QDropEvent会被触发,我们可以在事件过滤器中捕获这个事件,从而实现自定义的拖放逻辑。

4.2 利用事件过滤器优化性能

在Qt中,事件过滤器可以帮助我们优化性能。例如,我们可以通过事件过滤器拦截并忽略那些不必要的事件,从而减少事件处理的开销。

从底层原理的角度看,每当一个事件被发送到一个对象时,它都会经过事件过滤器。如果事件过滤器决定忽略这个事件,那么这个事件就不会被传递到目标对象,从而节省了处理事件的时间。

优化方法优点缺点
事件过滤减少不必要的事件处理可能会误拦截重要事件
代码优化提高代码执行效率需要深入了解算法和数据结构

事件过滤的工作原理
当我们安装了一个事件过滤器后,每当一个事件被发送到目标对象之前,它都会首先被发送到事件过滤器。事件过滤器可以决定是否继续传递这个事件,或者直接处理并结束这个事件。

这种机制为我们提供了一个在事件到达目标对象之前预处理事件的机会,从而实现更加灵活和高效的事件处理。

5 事件过滤的注意事项

5.1 避免过度过滤

在Qt中,事件过滤器(Event Filter)允许我们拦截并处理特定的事件。但是,过度使用事件过滤器可能会导致代码的复杂性增加,从而降低程序的性能。正如人们在面对信息过载时可能会感到困惑和疲惫,程序也可能因为处理大量不必要的事件而变得缓慢。

事件类型 (Event Type)处理方式 (Handling Method)是否推荐 (Recommendation)
鼠标事件 (Mouse Event)事件过滤器 (Event Filter)是 (Yes)
键盘事件 (Keyboard Event)事件过滤器 (Event Filter)否 (No)
自定义事件 (Custom Event)事件过滤器 (Event Filter)是 (Yes)

5.2 确保事件的正确传递

在Qt中,事件从发送者传递到接收者。如果事件没有被处理,它会继续传递给接收者的父对象。这种传递机制确保了事件能够被正确处理。但是,如果我们在事件过滤器中阻止了事件的传递,可能会导致某些功能无法正常工作。这就好像一个人在面对困难时选择逃避,而不是寻求帮助,最终可能会错过解决问题的机会。

在深入Qt的源码时,我们可以发现事件传递的核心逻辑是在QObject::event函数中实现的。这个函数确保了事件能够按照预定的顺序传递给各个对象。

事件传递的原理
当一个事件被发送时,它首先会被传递给目标对象的事件过滤器。如果事件过滤器没有处理这个事件,它会继续传递给目标对象的event函数。如果event函数也没有处理这个事件,它会继续传递给目标对象的父对象,直到事件被处理或传递到顶层对象。

这种事件传递的机制确保了事件能够被正确处理,同时也提供了灵活性,允许我们在不同的层级处理事件。

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

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

相关文章

<计算机网络自顶向下> 路由器组成

路由器结构概况 路由&#xff1a;运行路由选择算法/协议&#xff08;RIP, OSPF, BGP&#xff09;生成路由表转发&#xff1a;从输入到输出链路交换数据包-根据路由表进行分组的转发中间的fabric是用来接收输入的分组交给输出端口的&#xff0c;完成局部的转发&#xff08;根据…

在广东珠海,持有软考等证书最高可获6位数补贴,快来申报!

近日&#xff0c;横琴粤澳深度合作区执行委员会印发《横琴粤澳深度合作区支持人才发展若干措施》&#xff08;以下简称《若干措施》&#xff09;及三项配套实施办法&#xff0c;鼓励企业“招贤纳士”&#xff0c;加强琴澳人才协同培养。目前&#xff0c;2024年第一批博士后专项…

Java23种设计模式-结构型模式之组合模式

组合模式&#xff08;Composite Pattern&#xff09;&#xff1a;将对象组合成树状结构以表示“部分-整体”层次结构&#xff0c;同时保持对单个对象和组合对象的一致性操作&#xff0c;主要目的是简化客户端代码&#xff0c;因为它可以统一处理单个对象和组合对象。 通常包含…

星汉未来AI应用市场:一站式AI解决方案平台

星汉未来AI应用市场&#xff1a;一站式AI解决方案平台 在人工智能技术日益渗透到各行各业的今天&#xff0c;星汉未来AI应用市场为我们提供了一个集创新与实用于一体的平台。下面&#xff0c;我将为您详细介绍这个平台的各个方面。 平台特色 星汉未来AI应用市场是一个面向未…

Keil出现警告:warning: #223-D: function “XXX“ declared implicitly

这个警告表明编译器在函数使用之前没有找到函数的显式声明或定义。这通常发生在函数被使用之前没有在当前文件中进行声明或定义&#xff0c;或者头文件未正确包含。 解决方式&#xff1a; 在当前文件中添加函数声明&#xff1a;在使用函数之前&#xff0c;在当前文件中添加函…

华为OD机试真题-反射计数-2023年OD统一考试(C卷D卷)

题目描述: 给定一个包含 0 和 1 的二维矩阵 给定一个初始位置和速度 一个物体从给定的初始位置触发, 在给定的速度下进行移动, 遇到矩阵的边缘则发生镜面反射 无论物体经过 0 还是 1, 都不影响其速度 请计算并给出经过 t 时间单位后, 物体经过 1 点的次数 矩阵以左上角位置为[…

maixcam如何无脑运行运行别人的模型(以安全帽模型为例)

maixcam如何无脑运行运行别人的模型&#xff08;以安全帽模型为例&#xff09; 本文章主要讲如何部署上传的模型文件&#xff0c;以及如果你要把你模型按照该流程应该怎么修改&#xff0c;你可以通过该文章得到你想要的应该&#xff0c;该应用也包含的退出按钮&#xff0c;是屏…

低空经济和无人机

低空经济和无人机是当前科技领域中的两个热门话题&#xff0c;它们的发展互为促进&#xff0c;共同推动着低空经济持续发热&#xff0c;投资主线也愈发清晰。 低空经济是指以低空空域为活动场所&#xff0c;以各类低空飞行器为运载工具&#xff0c;所衍生的各类经济形态、经济…

书生·浦语大模型-第七节课笔记/作业

笔记 还没看到视频 但评测对于模型优化是非常重要的&#xff0c;指引了模型选择与优化的方向 评测过程 大海捞针&#xff1a; 通过将关键信息随机插入一段长文本的不同位置&#xff0c;形成大语言模型 (LLM) 的Prompt&#xff0c;通过测试大模型是否能从长文本中提取出关键…

协议的定制之序列化与反序列化 | 守护进程

目录 一、再谈协议 二、序列化与反序列化 三、网络计算器的简单实现 四、网络计算器完整代码 五、代码改进 六、守护进程 七、Json序列化与反序列化 八、netstat 一、再谈协议 是对数据格式和计算机之间交换数据时必须遵守的规则的正式描述。简单的说了&#xff0c;网络…

FFmpeg常用实例详解

FFmpeg 是一个专业的多媒体框架&#xff0c;能够解码、编码、转码、复用、解复用、流式传输、过滤和播放几乎所有格式的媒体文件。 这里通过一些示例简单地介绍下 ffmpeg 命令的基本使用。 一、获取详细信息 ffmpeg -i <inputfile> -hide_banner 其中 -hide_banner 选项…

佛山南海区桂城珠宝玉石电商协会举办2023年度电商企业颁奖典礼

4月24日&#xff0c;佛山市南海区桂城珠宝玉石电商协会隆重举办第一届三次会员大会暨2023年度电商企业颁奖典礼&#xff0c;广邀各级政府领导、行业组织、珠宝商场、电商企业、珠宝直播达人以及新闻媒体嘉宾&#xff0c;共见璀璨&#xff0c;共话新发展、新机遇。这是平洲玉器珠…

Java-GUI-AWT-组件-TextComponent类

1 需求 2 接口 java.lang.Object java.awt.Component java.awt.TextComponent Method Detail public void setText(String t)public String getText()public String getSelectedText()public boolean isEditable()public void setEditable(boole…

docker 启动时报错

docker 启动时报如下错误 Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details 因为安装docker时添加了镜像源 解决方案&#xff1a; mv /etc/…

汉译英早操练-(十八)

hello大家好&#xff0c;文接上回&#xff1a;https://blog.csdn.net/weixin_41953346/article/details/138184776 继续学习政府工作报告。 财政政策加力提 效&#xff0c;加强重点领域支出保障&#xff0c;全年新增税费优惠超过2.2万亿元&#xff0c;增发 1 万亿元国债支持灾 …

pwn--realloc [CISCN 2019东南]PWN5

首先学习一下realloc这个函数&#xff0c;以下是文心一言的解释&#xff1a; realloc是C语言库函数之一&#xff0c;用于重新分配内存空间。它的主要功能是调整一块内存空间的大小。当需要增加内存空间时&#xff0c;realloc会分配一个新的更大的内存块&#xff0c;然后将原内…

冯唐成事心法笔记 —— 知世

系列文章目录 冯唐成事心法笔记 —— 知己 冯唐成事心法笔记 —— 知人 冯唐成事心法笔记 —— 知世 冯唐成事心法笔记 —— 知智慧 文章目录 系列文章目录PART 3 知世 成事者的自我修养怎样做一个讨人喜欢的人第一&#xff0c;诚心第二&#xff0c;虚心 如何正确看待别人的评…

C#基础|OOP学习总结、优质的OOP程序有啥特点。

哈喽&#xff0c;你好&#xff0c;我是雷工。 以下为关于学习OOP的学习笔记。 01 OOP学习与基础语法有何不同 C#基础语法需要当时记住就行&#xff1b;OOP学习需要深入理解和记忆。 02 OOP学什么&#xff1f; OOP是学习各种编程的原则、方法、技巧、经验、模式、架构等。 …

超越边界:如何ChatGPT 3.5、GPT-4、DALL·E 3和Midjourney共同重塑创意产业

KKAI&#xff08;kkai人工智能&#xff09;是一个整合了多种尖端人工智能技术的多功能助手平台&#xff0c;融合了OpenAI开发的ChatGPT3.5、GPT4.0以及DALLE 3&#xff0c;并包括了独立的图像生成AI—Midjourney。以下是这些技术的详细介绍&#xff1a; **ChatGPT3.5**&#xf…

edge浏览器新建标签页闪退怎么解决?(打不开标签页)

文章目录 问题描述方法一方法二 问题描述 昨天开始出现这个问题&#xff0c;每次点击 打开一个新的标签页&#xff0c;马上就闪退了。 既然是新建标签页的问题&#xff0c;那么就在设置里看一下新建标签页发生了什么问题。 方法一 进入设置&#xff0c;会发现&#xff0c;有…