【Qt】Qt中的窗口坐标 信号与槽

news2024/9/29 5:47:25

Qt中的窗口坐标 && 信号与槽

  • 1. Qt中的窗口坐标
  • 2. 信号与槽的概述
  • 3. 信号和槽的使用
    • 3.1 connect函数的使用
    • 3.2 查看内置信号和槽
    • 3.2 connect的参数类型不匹配问题
  • 4. 自定义信号 && 自定义槽
    • 4.1 自定义槽
    • 4.2 自定义信号
  • 5. 带参数的信号和槽
  • 6. 信号与槽的关联方式
    • 6.1 一对一
    • 6.2 一对多 && 多对一
    • 6.3 多对多
  • 7. 信号与槽的断开
  • 8. 使用Lambda表达式定义槽
  • 9. 信号和槽的优缺点

1. Qt中的窗口坐标

在Qt中坐标系的开始是左上角(0,0),从在左上角往右依次增加的是x轴,从左上角往下依次增加的是y轴。

在这里插入图片描述

而在一个窗口中不止一个坐标系。对于嵌套窗口来讲,它的坐标是相对于父窗口来讲的

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 这个 button的父窗口就是Widget
    QPushButton* button = new QPushButton(this);
    button->setText("按钮");
    button->move(200, 200); // 这个就是设置坐标的函数,单位是像素点

    // 而对于Widget来讲,它的坐标轴就是我们当前的电脑屏幕
    this->move(200, 0);
}

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

在这里插入图片描述

我们可以将鼠标对准move函数然后按F1可以快速的查看文档。

在这里插入图片描述

2. 信号与槽的概述

  • 在 Qt 中,用户和控件的每次交互过程称为⼀个事件。比如 "用户点击按钮"是⼀个事件,“用户关闭窗口” 也是⼀个事件。每个事件都会发出⼀个信号,例如用户点击按钮会发出 “按钮被点击” 的信号,用户关闭窗口会发出 “窗口被关闭” 的信号。

  • Qt 中的所有控件都具有接收信号的能力,⼀个控件还可以接收多个不同的信号。对于接收到的每个信号,控件都会做出相应的响应动作。例如,按钮所在的窗口接收到 “按钮被点击” 的信号后,会做出 “关闭自己” 的响应动作;在 Qt 中,对信号做出的响应动作就称之为槽。 信号和槽是 Qt 特有的消息传输机制,它能将相互独立的控件关联起来。比如,“按钮” 和 “窗口” 本⾝是两个独立的控件,点击 “按钮” 并不会对 “窗口” 造成任何影响。通过信号和槽机制,可以将 “按钮” 和 “窗口” 关联起来,实现 “点击按钮会使窗口关闭” 的效果。

信号的本质:

  • 信号是由于用户对窗口或者控件进行操作,导致窗口或者控件触发了某些事件,这个时候Qt对应的窗口类会发出特定的信号,来对用户的操作进行处理。所以信号的本质就是事件

  • 而在Qt中常见的事件右:点击按钮,窗口刷新,移动鼠标,点击鼠标,键盘输入……。

信号的传递方式:

  • 首先我们对哪个窗口进行操作,哪个窗口就可以捕捉到这些触发的事件。
  • 对于使用者讲,触发的一个事件Qt框架都会给我们发出某个特定的信号。
  • 信号的呈现方式其实就是函数,也就是说事件发生了,Qt框架会调用这个函数通知事件触发者。
  • Qt中信号的发出者是某个示例化的类对象。

槽的本质:

  • 槽就是对信号做出响应的函数。槽就是⼀个函数,与⼀般的 C++ 函数是⼀样的,可以定义在类的任何位置( public、protected 或 private ),可以具有任何参数,可以被重载,也可以被直接调用(但是不能有默认参数)。槽函数与⼀般的函数不同的是:槽函数可以与⼀个信号关联,当信号被触发时,关联的槽函数被自动执行

槽和信号底层其实本质上都是函数称之为槽函数和信号函数,他们之间的关联方式其实就是函数之间的互相调用关系。例如按下按钮的信号函数式clicked(),关闭窗口的槽函数是close()。实现点击按钮关闭窗口其实就是信号函数clicked()函数调用了槽函数close()

信号函数和槽函数通常位于某个类中,和普通的成员函数相比,它们的特别之处在于:

  • 信号函数用 signals 关键字修饰,槽函数用 public slots、protected slots 或者 private slots 修饰signals slots 是 Qt 在 C++ 的基础上扩展的关键字,专门用来指明信号函数和槽函数;
  • 信号函数只需要声明,不需要定义(实现),而槽函数需要定义(实现)。

3. 信号和槽的使用

3.1 connect函数的使用

在QObject类中提供了一个静态函数connect(),该函数专门用来关联指定的信号函数和槽函数。其中QObject是Qt内置的一个类,Qt中提供的很多内置类都是直接或者间接的继承自QObject,所以像QWidget,QPushButton等都可以直接使用connect函数。

connect的函数原型:

QObject::connect(const QObject *sender,  // 信号的发送者
			     const char *signal, 	// 信号的类型
				 const QObject *receiver, // 信号的接收者
				 const char *method, 	// 信号的处理方式
				 Qt::ConnectionType type = Qt::AutoConnection // ⽤于指定关联⽅式,默认的关联⽅式为 Qt::AutoConnection,通常不需要⼿动设定。
				 )

所以我们就可以写一个demo代码来进行测试一下:

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 这个 button的父窗口就是Widget
    QPushButton* button = new QPushButton(this);
    button->setText("点击关闭函数");
    button->move(200, 200); // 这个就是设置坐标的函数,单位是像素点
    
    // 关联处理函数
    connect(button, &QPushButton::clicked, this, &QWidget::close);
}

3.2 查看内置信号和槽

在我们下载IDE的时候下载过了一个离线版本的文档。这个时候就需要去文档中寻找。

我们直接找到QPushButton类中找信号。但是因为Qt中存在许多的继承关系,所以我们搜素的类可能找不到对应的函数或者成员,这个时候就许需要到父类中查找。

在这里插入图片描述
所以这里我们就需要到QPushButton的父类中查找信号。

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

同理槽函数也是一样的道理。

3.2 connect的参数类型不匹配问题

这里我们重新回到connect函数的参数类型中我们会发现connect的第二个参数和第三个参数的的类型是const char*,但是我们实际传递的参数却是函数指针,这明显在C++中编译是会进行报错的,但是这里为什么没有报错呢?

在这里插入图片描述

在Qt5之前,我们是需要使用SIGNAL和SLOT宏来进行处理的,也就是写成:

connect(button, SINGAL(&QPushButton::clicked), this, SLOT(&QWidget::close));

但是在Qt5后进行了简化,并且还对connect函数进行了重载,我们可以去看看源码,这样就可以接收任意类型的了,而之所以文档写的是const char*,是因为没有对文档进行更新,所以一般我们看文档的时候都需要结合源码进行观看。

template <typename Func1, typename Func2>
    static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
                                     const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
                                     Qt::ConnectionType type = Qt::AutoConnection)
    {

4. 自定义信号 && 自定义槽

4.1 自定义槽

  1. 使用纯代码方式进行自定义槽

自定义槽函数其实跟定义一个函数是一样的

Widget.h

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots: // 在Qt4之前必须写上这个,这里也建议写上,利于区分
    void setTitle();

private:
    Ui::Widget *ui;
};

Widget.cpp

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* button = new QPushButton(this);
    button->setText("点击设置标题");
    button->move(200,200);
    connect(button, &QPushButton::clicked, this, &Widget::setTitle);
}

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

void Widget::setTitle()
{
    this->setWindowTitle("设置标题成功");
}

在这里插入图片描述

  1. 使用图形化设计自定义槽——使用函数名的方式进行将信号和槽进行关联

在这里插入图片描述

选择槽函数类型
在这里插入图片描述
此时Qt会自动生成一个在Widget.h帮我们生成一个函数声明,在Widget.cpp生成一个函数定义,我们就可以在这个函数定义里面写我们的事件了。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}
Widget::~Widget()
{
    delete ui;
}
// 这个就是Qt自动帮我们生成的
void Widget::on_pushButton_clicked()
{
    this->setWindowTitle("设置标题成功");
}

而这里我们也发现发现了,Qt帮我们生成的这个信号和槽并没有使用到connect函数,就算我们在qmake根据widget.ui生成的C++代码ui_widget.h代码中也没有使用到connect函数进行讲信号和槽进行关联起来。

这是因为Qt可以通过函数名来将信号和槽进行关联起来,我们可以发现Qt给我们生成的槽函数的命令为on_pushButton_clicked,我们可以分成三部分on,pushButton,clicked,其中这三部分on是固定的,pushButton是我们使用图形化界面拖拽出来的按钮的名称,而clicked是我们选择的槽函数,所以合起来的意思就是将pushButton这个按钮和clicked进行关联,一旦触发信号就执行on_pushButton_clicked这个函数。

而其实这是因为Qt调用道理ui_widget.h中的的一个函数自动连接了信号槽的规则:

QMetaObject::connectSlotsByName(Widget);

4.2 自定义信号

自定义信号有以下几个规则:

  • 自定义信号函数必须写到"signals”下。
  • 返回值必须是void,可以有参数,可以进行重载。
  • 只需要实现声明,不需要实现定义。

发送信号:

  • 使用 “emit” 关键字发送信号 。“emit” 是⼀个空的宏。“emit” 其实是可选的,没有什么含义,只是为了提醒开发⼈员。

Widget.h

namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    void Mysignal(); // 只需要实现声明即可
private slots:
    void on_pushButton_clicked();
    void Myslots();
private:
    Ui::Widget *ui;
};

Widget.cpp

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    connect(this, &Widget::Mysignal, this, &Widget::Myslots); // 将自定义信号和槽进行关联
}
Widget::~Widget()
{
    delete ui;
}
void Widget::on_pushButton_clicked()
{
    emit Mysignal(); // 发送信号
}
void Widget::Myslots()
{
    this->setWindowTitle("设置标题成功");
}

5. 带参数的信号和槽

信号和槽其实是可以带参数的,但是前提条件是槽函数的参数列表要和信号的参数列表一致,也就是说信号函数的参数类型是什么,槽函数的参数类型也必须是一样的,但是信号函数的参数列表可以比槽函数的参数列表多,前提是相同部分的位置的参数列表要相同。

Widget.h

class Widget : public QWidget
{
    Q_OBJECT 

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    void Mysignal(const QString&); // 只需要实现声明即可

private slots:
    void on_pushButton_clicked();
    void Myslots(const QString&);

private:
    Ui::Widget *ui;
};

Widget.cpp

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    connect(this, &Widget::Mysignal, this, &Widget::Myslots);
}

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

void Widget::on_pushButton_clicked()
{
    emit Mysignal("设置标题成功"); // 发送信号
}

void Widget::Myslots(const QString& str)
{
    this->setWindowTitle(str);
}

这里也提醒一下,我们一个类要使用信号和槽的话必须包含Q_OBGECT这个宏,不然的话就会出错报错。

6. 信号与槽的关联方式

6.1 一对一

  1. 一个信号连接一个槽

我们上述举的例子都是一个信号连接一个槽。

  1. 一个信号连接另一个信号

Widget.h

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
signals:
    void mysignal1();

public slots:
    void myslots();

private:
    Ui::Widget *ui;
};

Widget.cpp

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* button = new QPushButton(this);
    button->setText("点击按钮");

    connect(this, &Widget::mysignal1, &Widget::myslots);
    //信号关联信号
    connect(button, &QPushButton::clicked, this, &Widget::mysignal1);
}
Widget::~Widget()
{
    delete ui;
}
void Widget::myslots()
{
    this->setWindowTitle("设置标题成功");
}

6.2 一对多 && 多对一

  1. 一个信号关联多个槽
    widget.h
class Widget : public QWidget
{
    Q_OBJECT

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

public slots:
    void myslots1();
    void myslots2();
    void myslots3();

private:
    Ui::Widget *ui;
};

widget.cpp

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

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* button = new QPushButton(this);
    button->setText("点击按钮");
	
	// 一个信号关联多个槽
    connect(button, &QPushButton::clicked, this, &Widget::myslots1);
    connect(button, &QPushButton::clicked, this, &Widget::myslots2);
    connect(button, &QPushButton::clicked, this, &Widget::myslots3);
}

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

void Widget::myslots1()
{
    qDebug() << "myslots1";
}
void Widget::myslots2()
{
    qDebug() << "myslots2";
}

void Widget::myslots3()
{
    qDebug() << "myslots3";
}
  1. 多个信号关联一个槽

widget.h

class Widget : public QWidget
{
    Q_OBJECT

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

signals:
    void mysignal1();
    void mysignal2();
    void mysignal3();

public slots:
    void myslots1();
    void sentsignal();

private:
    Ui::Widget *ui;
};

widget.cpp

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

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* button = new QPushButton(this);
    button->setText("点击按钮");

    connect(button, &QPushButton::clicked, this, &Widget::sentsignal);
	
	// 多个信号关联一个槽函数
    connect(this, &Widget::mysignal1, this, &Widget::myslots1);
    connect(this, &Widget::mysignal2, this, &Widget::myslots1);
    connect(this, &Widget::mysignal3, this, &Widget::myslots1);
}

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

void Widget::myslots1()
{
    qDebug() << "myslots1";
}

void Widget::sentsignal()
{
    emit mysignal1();
    emit mysignal1();
    emit mysignal1();
}

6.3 多对多

其实到这里都大差不差了,同样是复用上述代码

connect(this, &Widget::mysignal1, this, &Widget::myslots1);
connect(this, &Widget::mysignal2, this, &Widget::myslots2);
connect(this, &Widget::mysignal2, this, &Widget::myslots1);
connect(this, &Widget::mysignal3, this, &Widget::myslots1);

7. 信号与槽的断开

使用 disconnect 即可完成断开.
disconnect 的用法和 connect 基本⼀致.

disconnect(this, &Widget::mysignal1, this, &Widget::myslots1);

8. 使用Lambda表达式定义槽

Lambda表达式 是 C++11 增加的特性。C++11 中的 Lambda表达式 用于定义并创建匿名的函数对象,以简化编程⼯作。

[ capture ] ( params ) opt -> ret { 
 Function body; 
};
  • capture 捕获列表
  • params 参数表
  • opt 函数选项
  • ret 返回值类型
  • Function body 函数体
符号说明
[ ]局部变量捕获列表。Lambda表达式不能访问外部函数体的任何局部变量
[a]在函数体内部使⽤值传递的⽅式访问a变量
[&b]在函数体内部使用引用传递的方式访问b变量
[=]函数外的所有局部变量都通过值传递的方式使用, 函数体内使用的是副本
[&]以引用的方式使用Lambda表达式外部的所有变量
[=, &foo]foo使用引用方式, 其余是值传递的方式
[&, foo]foo使用值传递方式,其余引用传递
[this]在函数内部可以使用类的成员函数和成员变量,= 和 & 形式也都会默认引入
  • 由于使用引用方式捕获对象会有局部变量释放了而Lambda函数还没有被调⽤的情况。如果执⾏Lambda函数,那么引⽤传递方式捕获进来的局部变量的值不可预知。所以绝大多数场合使用的形式为: [=] () { }
    •* 早期版本的 Qt,若要使用Lambda表达式,要在 “.pro” ⽂件中添加: CONFIG += C++11 因为 Lambda表式 是 C++11 标准提出的。Qt5 以上的版本无需手动添加,在新建项目时会自动添加。

在这里插入图片描述

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton* button = new QPushButton(this);
    button->move(200,200);
    button->setText("按钮");
    connect(button, &QPushButton::clicked, this, [=](){
        button->setWindowTitle("按钮被按下");
        button->move(300, 300);
    });
}

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

9. 信号和槽的优缺点

优点: 松散耦合

  • 信号发送者不需要知道发出的信号被哪个对象的槽函数接收,槽函数也不需要知道哪些信号关联了自己,Qt的信号槽机制保证了信号与槽函数的调用。支持信号槽机制的类或者父类必须继承于 QObject 类。

缺点: 效率较低

  • 与回调函数相比,信号和槽稍微慢⼀些,因为它们提供了更高的灵活性,尽管在实际应⽤程序中差别不大。通过信号调用的槽函数比直接调用的速度慢约10倍(这是定位信号的接收对象所需的开销;遍历所有关联;编组/解组传递的参数;多线程时,信号可能需要排队),这种调⽤速度对性能要求不是⾮常⾼的场景是可以忽略的,是可以满足绝大部分场景。

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

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

相关文章

leetcode_55:跳跃游戏

给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输…

C#由窗体原子表溢出造成的软件闪退的问题解决方法

报错信息 由于在MS.Win32.UnsafeNativeMethods.RegisterClassEx产生了报错信息&#xff0c;但是一直向外部抛出错误但始终没有被捕捉成功&#xff0c;直到报错被UI线程捕获&#xff0c;但是仍然没有进行处理&#xff0c;所有造成WPF的应用闪退。 解析报错信息 1.从异常初始位…

Camera Raw:打开图像

在图像工作流程中&#xff0c;无论是 Raw 格式图像文件还是 JPEG、TIFF 文件&#xff0c;都可以先使用 Camera Raw 打开并调整后&#xff0c;再进入其它 Adobe 软件如 Photoshop 中进行进一步的编辑和处理。 一、打开 Raw 格式图像 1、通过 Adobe Bridge 打开 在 Adobe Bridge …

Excel插件:dd统计与排名

Excel插件&#xff1a;dd统计与排名 使用教程 专门为学校成绩统计与排名设计的插件 一、安装后如图 二、 功能介绍&#xff1a; &#xff08;一&#xff09;单科统计与排名 1、 模板说明&#xff08;单科用&#xff09; 2、 单科三分四率统计 PS&#xff1a;可以设置界值&am…

哈希知识点总结:哈希、哈希表、位图、布隆过滤器

目录 哈希 哈希表 哈希常用方法 1、直接定址法 2、存留余数法 哈希冲突 哈希冲突的解决办法 1、闭散列&#xff1a;开放定址法 &#xff08;1&#xff09;线性探测法 &#xff08;2&#xff09;二次探测法 2、开散列 哈希桶 / 拉链法 哈希的运用 位图 set操作 …

07-阿里云镜像仓库

07-阿里云镜像仓库 注册阿里云 先注册一个阿里云账号&#xff1a;https://www.aliyun.com/ 进入容器镜像服务控制台 工作台》容器》容器服务》容器镜像服务 实例列表》个人实例 仓库管理》镜像仓库》命名空间》创建命名空间 仓库管理》镜像仓库》镜像仓库》创建镜像仓库 使…

c++11~c++20 内联命名空间

在工作&#xff0c;我们经常会引入第三方库&#xff0c;偶尔会碰到同名的函数和类型&#xff0c;造成编译冲突的问题。一般我们可以使用命名空间&#xff0c;例如 #include <iostream> #include <iostream> using namespace std;namespace S1 {void foo(){cout &l…

Meta首款多模态Llama 3.2开源:支持图像推理,还有可在手机上运行的版本 | LeetTalk Daily...

“LeetTalk Daily”&#xff0c;每日科技前沿&#xff0c;由LeetTools AI精心筛选&#xff0c;为您带来最新鲜、最具洞察力的科技新闻。 Meta最近推出的Llama Stack的发布标志着一个重要的里程碑。这一新技术的推出不仅为开发者提供了强大的多模态能力&#xff0c;还为企业和初…

重构部队信息安全:部队涉密载体建设新策略

一、完善保密体系架构 1. 加强保密规章制度&#xff1a;制定或刷新关于机密信息管理的相关规定&#xff0c;明确机密信息的生成、复制、传输、使用、储存及销毁等核心环节的操作准则与责任分配&#xff0c;确保整个流程的标准化运作。 2. 明确个人保密义务&#xff1a;通过保密…

古老的啤酒酿造技艺:传承与发扬

在人类文明的浩瀚历史中&#xff0c;啤酒酿造技艺源远流长&#xff0c;承载着世代匠人的智慧与匠心。这些古老的技艺&#xff0c;不仅是一种手艺&#xff0c;更是一种文化的传承。今天&#xff0c;我们将一起走进这神秘的酿造世界&#xff0c;探寻古老啤酒酿造技艺的传承与发扬…

性能调优知识点(mysql)三

SQL底层执行原理 MySQL的内部组件结构&#xff1a;大体来说&#xff0c;MySQL 可以分为 Server 层和存储引擎层store两部分 Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 MySQL 的大多数核心服务功能&#xff0c;以及所有的内置函数&#xf…

基于Python大数据可视化的民族服饰数据分析系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

基于51单片机的多通道数字电压表proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1zfDI2sjSGFHkYh33Sw6gHQ 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectron…

【数据结构】链表(1)

【概念】 一种物理存储结构上的非连续存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引用链接次序来实现的 也就是说&#xff0c;链表是由一个一个的节点组织起来的&#xff0c;如车厢一般&#xff0c;整体就叫做链表 【链表结构】 节点可以理解为”节点对象“&#…

详解代理模式-【静态代理与JDK动态代理】(非常的斯国一)

目录 静态代理 什么是静态代理: ​ 特点: 例子&#xff1a; JDK动态代理&#xff08;主要讲点&#xff09; 大纲&#xff1a; 1、与静态代码的联系 2、JDK动态代理的主流程 3、Proxy的源码 整体概述&#xff1a; 重要点的翻译 &#xff1a; newProxyInstance源码&am…

Adobe Photoshop 2024 v25.12 (macOS, Windows) 发布下载 - 照片和设计软件

Adobe Photoshop 2024 v25.12 (macOS, Windows) - 照片和设计软件 Acrobat、After Effects、Animate、Audition、Bridge、Character Animator、Dimension、Dreamweaver、Illustrator、InCopy、InDesign、Lightroom Classic、Media Encoder、Photoshop、Premiere Pro、Adobe XD…

算法宝典——二分查找算法

1.认识二分查找 二分查找的时间复杂度:O(logN) 二分查找属于算法中耳熟能详的一类&#xff0c;通常的我们会说只有数组有序才可以使用二分查找&#xff0c;不过这种说法并不完全正确&#xff0c;只要数据具有"二段性"就可以使用二分查找&#xff0c;即我们可以找出一…

Spring 事务管理-AOP

1. 事务管理 1.1 事务回顾 概念 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;这些操作要么同时成功&#xff0c;要么同时失败。 操作 开启事务(一组造作开始前&#xff0c;开启事务)&#xff1a;start transaction / begin ; 提交事务(这组操…

网络:TCP协议-报头字段

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》《网络》 文章目录 前言一、TCP协议格式16位源端口号 和 16位目的端口号4位首部长度16位窗口大小32位序号 和 32位确认序号6种标记位 和 16位紧急指针 总结 前言 本文是我对于TCP协…

毕业设计选题:基于ssm+vue+uniapp的校园二手交易平台小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…