QT消息机制和事件 - 鼠标事件、键盘按下事件、绘图事件、定时器事件处理

news2024/12/25 0:02:20

事件

  • 事件(event)是由系统或者Qt本身在不同时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事件。一些事件在对用户操作做出响应时发出,如键盘事件等。另一些事件则由系统自动发出,如定时器事件。

Qt消息循环机制

  • Qt程序需要在main函数创建一个QApplication对象,然后调用它的exec函数,这个函数就是开始Qt的事件循环。在执行exec函数之后,程序将进入事件循环来监听应用程序的事件。
  • 当应用程序监听到事件触发后,先将请求交给事件过滤器,过滤后再交给事件分发器,由事件分发器交给具体的事件处理器进行处理。
    在这里插入图片描述
  • 事件过滤器,事件分发器和事件处理器,默认都会对事件进行处理,如果我们想要自己处理事件,就重写对应的事件函数。然后在对应的事件函数中,进行相应的处理。
  • 一般来说,重写事件处理函数的场景比较多,事件过滤和事件分发,基本上交给系统处理就可以了,我们不用自己处理。为了说明事件过滤器和事件分发器的作用,因此下面也重写了事件过滤函数和事件分发函数。
  • 由于重写事件处理器函数比较常用,阅读时可以先查看事件处理,再查看事件过滤和事件分发。

事件过滤

事件过滤函数

  • bool eventFilter(QObject *watched, QEvent *event);
  • 返回值是bool类型,如果返回true,表示用户要处理这个事件,不向下分发事件。

示例

  • 头文件
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      
      namespace Ui {
      class Widget;
      }
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
      
          // 键盘按下事件
          void keyPressEvent(QKeyEvent *event);
      
          // 事件分发
          bool event(QEvent* ev);
      
          // 重写事件过滤器函数
          bool eventFilter(QObject *watched, QEvent *event);
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • 源文件
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      #include <QMouseEvent>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
      
          // 安装事件过滤器
          installEventFilter(this);
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::keyPressEvent(QKeyEvent *event)
      {
          // 判断键盘按下事件
          if(event->type() == QEvent::KeyPress){
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
                  QMessageBox::question(this, "提示", "事件处理函数中Tab键按下", QMessageBox::Yes);
              }
          }
      }
      
      bool Widget::event(QEvent *ev)
      {
          // 判断键盘按下事件
          if(ev->type() == QEvent::KeyPress){
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
                  QMessageBox::question(this, "提示", "事件分发函数中Tab键按下", QMessageBox::Yes);
      
                  // 返回true, 表示自己处理这个事件,不向下分发了,这样对应的事件处理函数就接收不到该事件了
                  return true;
              }
          }
      
          // 其他事件交给父类,默认处理
          return QWidget::event(ev);
      }
      
      bool Widget::eventFilter(QObject *watched, QEvent *event)
      {
          // 判断是哪个窗口,这里是当前窗口
          if(watched == this){
      
              if(event->type() == QEvent::KeyPress){
                  QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
                  // 判断按下的是否为tab键
                  if(keyEvent->key() == Qt::Key_Tab){
                      QMessageBox::question(this, "提示", "Tab键按下", QMessageBox::Yes);
      
                      // 返回true, 表示自己处理这个事件,不向下分发了
                      // 这样不仅事件处理函数接收不到该事件,事件分发函数也接受不到该事件
                      return true;
                  }
              }
          }
      
      	// 其他事件交给系统处理
          return QWidget::eventFilter(watched, event);
      }
    
    
  • 如果在事件过滤器中处理了事件并且不往下传递,那么在事件分发器和事件处理器都不会接收到相应的事件。

事件分发

事件分发函数

  • bool event(QEvent* ev);
  • 返回值是bool类型,如果返回true,表示用户要处理这个事件,不向下分发事件。

示例

  • 下来通过一个例子演示下,在事件分发函数中,处理键盘的tab键按下事件,并且处理后不向下传递,这样对应的事件处理函数就接收不到该事件了。
  • 头文件
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      
      namespace Ui {
      class Widget;
      }
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
      
          // 键盘按下事件
          void keyPressEvent(QKeyEvent *event);
      
          // 事件分发
          bool event(QEvent* ev);
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • 源文件
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      #include <QMouseEvent>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::keyPressEvent(QKeyEvent *event)
      {
          // 判断键盘按下事件
          if(event->type() == QEvent::KeyPress){
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
                  QMessageBox::question(this, "提示", "事件处理函数中Tab键按下", QMessageBox::Yes);
              }
          }
      }
      
      bool Widget::event(QEvent *ev)
      {
          // 判断键盘按下事件
          if(ev->type() == QEvent::KeyPress){
              QKeyEvent* keyEvent = static_cast<QKeyEvent*>(ev);
              // 判断按下的是否为tab键
              if(keyEvent->key() == Qt::Key_Tab){
                  QMessageBox::question(this, "提示", "Tab键按下", QMessageBox::Yes);
      
                  // 返回true, 表示自己处理这个事件,不向下分发了,这样对应的事件处理函数就接收不到该事件了
                  return true;
              }
          }
      
      
          // 其他事件交给父类,默认处理
          return QWidget::event(ev);
      }
    
  • 演示
    在这里插入图片描述
  • 通过示例可以看到,虽然在事件处理函数中对tab键按下进行了处理,但由于在事件分发函数中,并未向下传递tab键按下事件,因此事件处理函数并未被触发。

事件处理

  • 事件触发后,先经过事件过滤器进行过滤,再经过事件分发器,下发到具体的事件处理器中,默认事件处理器也会自动处理事件,如果想要自己处理,就可以重写事件处理函数。
  • QObject类是所有Qt类的父类,因此所有Qt类都可以继承QObject类的事件处理函数,QObject类的事件函数主要是定时器事件函数,由系统自动触发
  • QWidget类是所有Qt窗口类的事件函数,因此所有Qt窗口类都可以继承QWidget类的事件处理函数,QWidget类的事件函数比较多,比如键盘按下事件,鼠标移动事件等,QWidget类的事件函数,主要由用户触发

QObject类的事件处理函数

  • 定时器事件函数
  • virtual void timerEvent(QTimerEvent *event)

QWidget类的事件处理函数

  • 窗口关闭事件函数
  • virtual void closeEvent(QCloseEvent *event)
  • 窗口隐藏事件函数
  • virtual void hideEvent(QHideEvent *event)
  • 窗口显示事件函数
  • virtual void showEvent(QShowEvent *event)
  • 窗口重设大小事件函数
  • virtual void resizeEvent(QResizeEvent *event)
  • 键盘按下事件函数
  • virtual void keyPressEvent(QKeyEvent *event)
  • 键盘松开事件函数
  • virtual void keyReleaseEvent(QKeyEvent *event)
  • 鼠标双击事件函数
  • virtual void mouseDoubleClickEvent(QMouseEvent *event)
  • 鼠标移动事件函数
  • virtual void mouseMoveEvent(QMouseEvent *event)
  • 鼠标按下事件函数
  • virtual void mousePressEvent(QMouseEvent *event)
  • 鼠标松开事件函数
  • virtual void mouseReleaseEvent(QMouseEvent *event)
  • 绘图事件函数
  • virtual void paintEvent(QPaintEvent *event)

示例1:窗口事件处理

  • 接下来我们通过一个例子来演示下对窗口关闭窗口重设大小的事件如何处理
  • 创建一个类,继承于QWidget类
  • 头文件
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      
      namespace Ui {
      class Widget;
      }
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
          // 重写窗口关闭事件函数
          void closeEvent(QCloseEvent *event);
          // 重写重绘窗口大小事件函数
          void resizeEvent(QResizeEvent *event);
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • 源文件
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QCloseEvent>
      #include <QResizeEvent>
      #include <QDebug>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::closeEvent(QCloseEvent *event)
      {
          int retStatus = QMessageBox::question(this, "提示", "确定关闭窗口吗?", QMessageBox::Yes | QMessageBox::No);
          if(retStatus == QMessageBox::Yes){
              // 处理该事件,也就是关闭窗口
              event->accept();
          }else{
              // 忽略该事件,也就是不关闭窗口
              event->ignore();
          }
      }
      
      void Widget::resizeEvent(QResizeEvent *event)
      {
          qDebug()<<"old size : "<<event->oldSize();
          qDebug()<<"new size : "<<event->size();
      }
    
  • 效果展示
    请添加图片描述
    请添加图片描述

示例2:鼠标事件处理

  • 再实现一个对鼠标按下鼠标松开鼠标移动的事件处理流程。
  • 头文件
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      
      namespace Ui {
      class Widget;
      }
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
          // 重写鼠标按下事件
          void mousePressEvent(QMouseEvent* event);
          // 重写鼠标松开事件
          void mouseReleaseEvent(QMouseEvent* event);
          // 重写鼠标移动事件
          void mouseMoveEvent(QMouseEvent* event);
      
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • 源文件
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      #include <QMouseEvent>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
      
          // 设置鼠标被追踪
          // 不设置该属性,鼠标按下移动时才能触发鼠标移动事件函数
          // 设置该属性后,不管鼠标是否按下,鼠标移动事件函数都会被触发
          // this->setMouseTracking(true);
      
          ui->label->setText("鼠标正常");
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::mousePressEvent(QMouseEvent *event)
      {
          if(event->button() == Qt::LeftButton){
              ui->label->setText("鼠标左键按下");
          }else if(event->button() == Qt::RightButton){
              ui->label->setText("鼠标右键按下");
          }else{
              ui->label->setText("鼠标按下");
          }
      }
      
      void Widget::mouseReleaseEvent(QMouseEvent *event)
      {
          ui->label->setText("鼠标松开");
      }
      
      void Widget::mouseMoveEvent(QMouseEvent *event)
      {
          QString msg;
          msg = "鼠标移动(" + QString::number(event->x()) + "," + QString::number(event->y()) + ")";
          ui->label->setText(msg);
      }
    
  • 效果展示
    请添加图片描述
    请添加图片描述

示例3:绘图事件处理

  • 处理绘图事件算是很常用的一个功能,下面通过一个示例进行简单说明
  • 头文件
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      #include <QPainter>
      
      namespace Ui {
      class Widget;
      }
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      protected:
      
          // 绘图事件
          void paintEvent(QPaintEvent* e);
      
      private:
          Ui::Widget *ui;
      };
      
      #endif // WIDGET_H
    
  • 源文件
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
      
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::paintEvent(QPaintEvent *e)
      {
          // 实例化画家对象, this表示绘图设备是当前窗口
          QPainter painter(this);
      
          // 画线
          painter.drawLine(QPoint(0, 0), QPoint(100, 100));
      
          // 设置画笔(红色)
          QPen pen(QColor(255, 0, 0));
      
          // 设置画笔宽度
          pen.setWidth(3);
          // 设置画笔风格
          pen.setStyle(Qt::DotLine);
          painter.setPen(pen);
      
          // 画矩形
          painter.drawRect(QRect(0, 0, 100, 100));
      
          // 设置画刷
          QBrush brush(Qt::green);
          // 设置画刷风格
          brush.setStyle(Qt::Dense1Pattern);
          painter.setBrush(brush);
      
          // 画圆
          painter.drawEllipse(QPoint(150, 50), 50, 50);
      
          // 画文字
          painter.drawText(QRect(0, 150, 150, 150), "HELLO");
      
          // 画图片
          painter.drawPixmap(100, 100, QPixmap(":/gray.jpg"));
      }
    
  • 演示
    在这里插入图片描述
  • 绘图事件比较特殊,默认是系统自动触发,但是还可以手动进行触发,那就是在函数中调用 update() 函数,调用之后也会自动触发绘事件,对应的绘图事件处理函数会被执行。比如可以在鼠标点击槽函数中调用 update() 函数,这里就不进行演示了。

示例4:定时器事件处理

  • 定时器事件由系统触发,可以重写处理函数,在其中进行相应操作,这也是非常常用的一个功能。
  • 头文件
  •   #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QEvent>
      #include <QTimerEvent>
      
      namespace Ui {
      class Widget;
      }
      
      class Widget : public QWidget
      {
         Q_OBJECT
      
      public:
         explicit Widget(QWidget *parent = 0);
         ~Widget();
      protected:
      
         // 定时器事件处理函数
         void timerEvent(QTimerEvent *e);
      
      private:
         Ui::Widget *ui;
      
         // 定时器id
         int timerId;
      };
      
      #endif // WIDGET_H
    
  • 源文件
  •   #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
      
          // 启动定时器,定时事件为1秒
          timerId = startTimer(1000);
      }
      
      Widget::~Widget()
      {
          // 停止定时器
          killTimer(timerId);
      
          delete ui;
      }
      
      void Widget::timerEvent(QTimerEvent *e)
      {
          qDebug()<<"定时器事件触发";
      }
    

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

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

相关文章

大学里学编程,为什么这么难?

在大学学习计算机专业&#xff0c;为何很多同学觉得编程学得不顺心呢&#xff1f;许多同学会有这种感觉&#xff0c;在上大学里的计算机专业课程时&#xff0c;听得头都大了&#xff0c;但是真正要写代码&#xff0c;却不知道从哪里开始&#xff0c;或是觉得&#xff0c;大学里…

redis------在java中操作redis

Redis&#xff08;非关系型数据库&#xff09;简介 redis下载 点击即可进入redis中文网进行下载 百度网盘windows版本 提取码 DMH6 redis主要特点 基于内存存储&#xff0c;读写性能高 适合存储热点数据&#xff08;热点商品、资讯、新闻&#xff09; 企业应用广泛 redis不同…

[计算机网络] 高手常用的几个抓包工具(下)

文章目录 高手常用的抓包工具一览什么是抓包工具优秀抓包工具HTTP Debugger ProFree Network AnalyzerKismetEtherApeNetworkMiner 结尾 高手常用的抓包工具一览 什么是抓包工具 抓包工具是一种可以捕获、分析和修改网络流量的软件。它可以帮助您进行网络调试、性能测试、安全…

VSCode 开发C/C++实用插件分享——codegeex

VSCode 开发C/C实用插件分享——codegeex 一、codegeex 一、codegeex CodeGeeX 智能编程助手是一款编程插件&#xff0c;CodeGeeX支持多种主流IDE&#xff0c;如VS Code、IntelliJ IDEA、PyCharm、Vim等&#xff0c;同时&#xff0c;支持Python、Java、C/C、JavaScript、Go等多…

内存管理+模板初阶

内存管理模板初阶 一&#xff0c;内存管理1.1new和delete1.2语法规范补充重点&#xff08;malloc/free和new/delete的区别和联系&#xff09; 二&#xff0c;模板初阶2.1泛型编程2.2模板函数2.3函数模板格式2.4类模板 一&#xff0c;内存管理 我们在c语言学习了动态开辟内存&a…

群晖Video Station 添加海报墙-新方法

海报墙 一般我们找到的都是mp4、mkv等格式的视频资源&#xff0c;而没有像上图这样的海报资源&#xff0c;那要怎样实现海报墙呢&#xff1f; 按照以前的方法&#xff0c;是可以通过The Movie Database的API Key来搜刮电影海报信息&#xff0c;但是现在这个方法不行了 现在介绍…

134. 加油站(贪心算法)

根据题解 这道题使用贪心算法&#xff0c;找到当前可解决问题的状态即可 「贪心算法」的问题需要满足的条件&#xff1a; 最优子结构&#xff1a;规模较大的问题的解由规模较小的子问题的解组成&#xff0c;规模较大的问题的解只由其中一个规模较小的子问题的解决定&#xff…

Linux基础项目开发1:量产工具——UI系统(四)

前言&#xff1a; 前面我们已经把显示系统、输入系统、文字系统搭建好了&#xff0c;现在我们就要给它实现按钮操作了&#xff0c;也就是搭建UI系统&#xff0c;下面让我们一起实现UI系统的搭建吧 目录 一、按钮数据结构抽象 ui.h 二、按键编程 1.button.c 2.disp_manager…

C++作业4

代码整理&#xff0c; 将学过的三种运算符重载&#xff0c;每个至少实现一个运算符的重载 代码&#xff1a; #include <iostream>using namespace std;class Stu {friend const Stu operator*(const Stu &L,const Stu &R);friend bool operator<(const Stu …

软著项目推荐 深度学习疲劳驾驶检测 opencv python

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

【UGUI】Unity为下拉菜单添加选项(DropDown)

要想控制谁就把谁拿到代码里-获取组件-修改组件参数&#xff08;变量或者方法&#xff09; 代码示例&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using TMPro;public class UIcontrol : MonoBehavi…

今天给大家分享一套Python入门基础测试题,大家看看都会做吗?

今天给大家分享一套Python入门基础测试题&#xff0c;大家看看都会做吗&#xff1f; 一、测试题 1. 正确下载Anaconda平台或Python安装包并成功安装。 2. 掌握Python注释与print()和input()两个函数的用法&#xff0c;并作答以下选择题&#xff08;不定项选择&#xff0c;正…

【算法】动态规划中的路径问题

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;如果给算法的难度和复杂度排一个排名&#xff0c;那么动态规划算法一定名列前茅。今天&#xff0c;我们通过由简单到困难的两道题目带大家学会动…

根目录/ 空间不够,扩容,导致web页面无法加载问题

现象就是&#xff1a;搭建的web页面无反应&#xff0c;也没报错&#xff0c;怀疑是内存空间不够导致的。/ 扩容步骤如下&#xff1a; 虚拟机为关机状态添加虚拟磁盘 #查看磁盘&#xff0c;并创建新分区 fdisk -l fdisk /dev/sdb p       查看已分区数量&#xff08;我看…

在cmd下查看mysql表的结构信息

我提前已经在mysql数据库中创建了一个表&#xff1a; 在cmd下&#xff0c;登录mysql以后&#xff0c;使用命令describe 表名、或者explain 表名可以查看表结构信息。但在实践中&#xff0c;查看表结构&#xff0c;多用describe命令&#xff0c;而查看执行计划用explain。 例…

FreeRtos第一个task是怎么run起来的

第一个task是怎么起来的呢&#xff1f;分析完vTaskStartScheduler&#xff0c;就会有答案了。 那vTaskStartScheduler()干了啥呢&#xff1f; 一、创建prvIdleTask task 二、xTimerCreateTimerTask里创建prvTimerTask task 三、初始化一些全局变量 3.1 xNextTaskUnblockTime…

计算机组成学习-数据的表示和运算总结

1、进制与编码 1.1 进位计数法 常用的进位计数法有十进制、二进制、八进制、十六进制等。十六进制每个 数位可取0〜9、A、B、C、D、E、F中的任意一个&#xff0c;其中A、B、C、D、E、F分别表示 10〜15。 八进制数字通常以前缀 "0"&#xff08;零&#xff09;加上数…

前端文本省略号后面添加复制文字

前端文本省略号后面添加复制文字 1、效果图 2、代码展示 <div class"link-content-wrap" click"copyLinkText"><div class"link-content">{{ shareResult.url || }} </div><span class"show-ellipsis" click&…

「C++」哈希表的实现(unordered系底层)

&#x1f4bb;文章目录 &#x1f4c4;前言哈希表概念哈希函数 哈希冲突闭散列开散列 &#x1f4d3;总结 &#x1f4c4;前言 unordered系列的关联式容器之所以效率比较高,是因为其底层使用了哈希结构&#xff0c;使其在查找上的时间复杂度几乎减低到了 O ( 1 ) O(1) O(1)。 哈希…

微信扫码登录的两种方式:利用微信开放平台、利用微信公众平台(微信公众号)

微信扫码登录&#xff0c;有两种实现方式&#xff1a; 方式1、微信开放平台是微信为了接入更多第三方应用而开放的接口&#xff0c;依赖公司在【微信开放平台】用【公司营业执照】注册的账号&#xff0c;才能实现扫码登录 方式2、微信公众平台是扫码通过微信公众号授权登录的&a…