Qt元对象系统

第二章Qt元对象系统

文章目录

  • 第二章Qt元对象系统
  • 1.什么是元对象?
  • 2.元对象系统组成
  • 3.信号与槽
    • 信号和槽的本质
    • 绑定信号与槽
    • 自定义槽
      • 定义槽函数必须遵循一下规则
      • 槽函数的类型
      • 自定义槽案例
    • 自定义信号
      • 自定义信号需要遵循以下规则
      • 信号和槽重载二义性问题
  • 4.内存管理
    • 1. 简介
    • 2.关联图
    • 3.详解
    • 4.智能指针
  • 5.属性系统
    • 获取/设置属性值
    • 自己声明属性值
    • 绑定属性
    • QObjectBindableProperty
  • 6.实时类型信息
  • 枚举
  • QMetaObject元信息

元对象系统是一个基于标准C++的扩展,为QT提供了新号与槽机制、实时类型信息、动态属性系统

1.什么是元对象?

在计算机科学中,元对象是这样一个东西:它可以操纵、创建、描述或执行其他对象。元对象描述的的对象称为基对象。元对象可能存在这样的信息:基础对象的类型、接口、类、方法、属性、变量、控制结构等。

2.元对象系统组成

  • QObject
    是QT对象模型的核心,绝大部分的QT类都是从这个类继承而来

  • Q_OBJECT
    Q_OBJECT宏必须出现在类定义的私有部分,用来开启信号和槽、动态属性系统,或QT元对象系统提供的其他服务

  • MOC
    MOC编译器为QObject子类提供了一些实现元对象特性所需要的一些代码。比如说信号,大家只是在类声明的时候声明了所需要的信息,在MOC编译时,会为信号添加函数定义。

3.信号与槽

所谓信号槽,实际就是观察者模式(发布-订阅模式)。当某个时间发生之后,比如按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽-slot)绑定来处理这个信号。也就是说,信号发出时,被连接的槽函数会自动被回调。

信号和槽的本质

信号是由对象发射出去的消息,信号实际上是一个特殊的函数,不需要由程序员实现,而是由QT的moc实现。
槽实际上就是普通的函数。
当我们把对象的信号和槽绑定在一起之后,当信号触发时,与之绑定的槽函数将会自动调用,并把信号参数传递给槽函数。

绑定信号与槽

使用QObject::connect()函数实现

#	Mainwindow.ui
# 创建一个PushButton
# 	Mainwindow.h 在下面加入代码
public slots:void onButtonClicked();
# Mainwindow.cpp
#include "MainWindow.h"
#include "./ui_MainWindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);auto con =connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(onButtonClicked()));QObject::connect(ui->pushButton_2,&QPushButton::clicked,this,&MainWindow::onButtonClicked);//lambda函数写法connect(ui->pushButton_3,&QPushButton::clicked,[=](){disconnect(con);qInfo()<<"断开1的连接";});
}
MainWindow::~MainWindow()
{delete ui;
}void MainWindow::onButtonClicked()
{qInfo()<<"我被点击了";
}

自定义槽

槽函数就是信号的处理动作,自定义槽函数和自定义的普通函数写法是一样的。只不过自定义的槽函数一般放在public slots:后面。

定义槽函数必须遵循一下规则

  1. 槽函数的返回类型必须是void
  2. 槽函数的参数必须等于或少于信号的参数
  3. 当信号与槽函数的参数数量相同时,它们参数类型要完全一致。

槽函数的类型

  • 成员函数
    • 普通成员函数
    • 静态成员函数
  • 全局函数
  • lambda表达式

自定义槽案例

#include <QApplication>
#include <QWidget>
#include<QPushButton>class MyWindow:public QWidget
{Q_OBJECT
public:MyWindow():QWidget(NULL){}
public slots:void showWindow(){this->show();}
};int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton* btn = new QPushButton("打开");btn->show();MyWindow *mw=new MyWindow();auto con = QObject::connect(btn,&QPushButton::clicked,mw,&MyWindow::showWindow);return a.exec();
}#include "main.moc"

自定义信号

Qt框架提供的信号在某些特定场景下是无法满足我们的项目需求的,因此我们还设计自己需要的信号,同样还是使用connect()对接

自定义信号需要遵循以下规则

  • 信号是类的成员函数,并且返回类型必须是void
  • 信号函数只需要声明,不需要定义
  • 参数可以随意指定,信号也支持重载
  • 信号需要使用signals关键字进行声明
  • 在程序中发送自定义信号:发送信号的本质就是调用信号函数emit mysignals()
  • emit是个空宏,没有特殊含义,仅用来表示这个语句是发射一个信号,不写可以,但不推荐
#include <QApplication>
#include <QWidget>
#include<QPushButton>class MyWindow:public QWidget
{Q_OBJECT
public:MyWindow():QWidget(NULL){}
signals:void isShow(QString text);
public slots:void showWindow(){this->show();emit isShow("我出来了");}
};int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton* btn = new QPushButton("打开");btn->show();MyWindow *mw=new MyWindow();auto con = QObject::connect(btn,&QPushButton::clicked,mw,&MyWindow::showWindow);QObject::connect(mw,&MyWindow::isShow,btn,&QPushButton::setText);return a.exec();
}#include "main.moc"

信号和槽重载二义性问题

解决方法


#include <QApplication>
#include <QWidget>
#include<QPushButton>class MyWindow:public QWidget
{Q_OBJECT
public:MyWindow():QWidget(NULL){}
signals:void isShow();void isShow(QString text);public slots:void showWindow(){this->show();emit isShow("我出来了");}void showWindow(bool t){this->close();emit isShow();}
};int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton* btn = new QPushButton("打开");btn->move(10,10);btn->show();QPushButton* btn1 = new QPushButton("关闭");btn1->move(10,100);MyWindow *mw=new MyWindow();//用overload重载QObject::connect(btn,&QPushButton::clicked,mw,QOverload<>::of(&MyWindow::showWindow));QObject::connect(mw,QOverload<QString>::of(&MyWindow::isShow),btn,&QPushButton::setText);//用qt4方式SIGNAL和SLOT宏QObject::connect(btn1,SIGNAL(clicked(bool)),mw,SLOT(showWindow(bool)));//SIGNAL和SLOT要前后一致QObject::connect(mw,SIGNAL(isShow()),btn1,SLOT(close()));QObject::connect(mw,SIGNAL(isShow(QString)),btn1,SLOT(show()));return a.exec();
}#include "main.moc"

4.内存管理

1. 简介

C++中new 和delete必须配对使用,防止内存泄露。Qt中使用了new却很少delete,因为Qt实现了其独特的内存管理机制。
QObject以对象树的形式组织起来。当为一个对象创建子对象时,子对象会自动地添加到父对象的children()列表中。父对象拥有子对象的所有权,比如父对象可以在自己的析构函数中删除它的子对象。使用findChild()或findChildren()通过名字和类型查询孩子对象。

QObject(QObject *parent=nullptr)
  1. QObject及其派生类的对象,如果其parent非nullptr,那么其parent析构时会析构该对象。
  2. 父子关系:父对象、子对象、父子关系。这是Qt中所特有的,与类的继承关系无关,传递参数是与parent有关

2.关联图

在Qt中,最基础和核心的类是QObject,QObject内部有一个名为children的QObjectList列表,会保存所有子对象,还有一个指针parent,用来指向父对象,当自己析构时,会先把自己从parent列表中删除,并且析构所有的child
在这里插入图片描述

3.详解

  1. 指定父对象释放,自己也释放

#include <QApplication>
#include <QWidget>
#include<QPushButton>class MyWindow:public QWidget
{Q_OBJECT
public:MyWindow(QWidget* parent=nullptr):QWidget(parent){}~MyWindow(){qInfo()<<__FUNCTION__<<"释放了";}
signals:void isShow();void isShow(QString text);public slots:void showWindow(){this->show();emit isShow("我出来了");}void showWindow(bool t){this->close();emit isShow();}
};int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton* btn = new QPushButton("打开");btn->move(10,10);btn->show();QPushButton* btn1 = new QPushButton("关闭");btn1->move(10,100);MyWindow *mw=new MyWindow(btn1);//用overload重载QObject::connect(btn,&QPushButton::clicked,mw,QOverload<>::of(&MyWindow::showWindow));QObject::connect(mw,QOverload<QString>::of(&MyWindow::isShow),btn,&QPushButton::setText);//用qt4方式SIGNAL和SLOT宏QObject::connect(btn1,SIGNAL(clicked(bool)),mw,SLOT(showWindow(bool)));//SIGNAL和SLOT要前后一致QObject::connect(mw,SIGNAL(isShow()),btn1,SLOT(close()));QObject::connect(mw,SIGNAL(isShow(QString)),btn1,SLOT(show()));btn1->deleteLater();return a.exec();
}#include "main.moc"
  1. 查找子对象
	mw->setObjectName("window");auto wd =btn1->findChild<MyWindow*>("window"); //找子对象if(wd)qInfo()<<"存在";

4.智能指针

智能指针描述
QPointerQObject或子类对象释放时会自动指向nullpter
QScopedPointer【独享指针】超出作用域自动释放管理的对象
QSharedPoiner【共享指针】
QWeakPointer【监视指针】
QScopedArrayPointer【独享数组指针】超出作用域自动释放管理的对象数组
QSharedDataPointer【隐式共享指针】读时共享,写时拷贝
QExplicitlySharedDataPointer【显式共享指针】读时共享,写时需要手动拷贝(通过detach()函数)
  • 使用方法
	#include<QPointer>QPointer<QPushButton> btn1 = new QPushButton("关闭");btn1->move(10,100);MyWindow *mw=new MyWindow(btn1.data());
	#include<QSharedPointer>QSharedPointer<QPushButton> btn1(new QPushButton("关闭"));QObject::connect(btn1.data(),SIGNAL(clicked(bool)),mw,SLOT(showWindow(bool)));//SIGNAL和SLOT要前后一致QObject::connect(mw,SIGNAL(isShow()),btn1.data(),SLOT(close()));QObject::connect(mw,SIGNAL(isShow(QString)),btn1.data(),SLOT(show()));
	#include<QScopedArrayPointer>QScopedArrayPointer<int> arrptr(new int[10]);arrptr[1] = 666;

5.属性系统

属性的行为类似于数据成员,但它具有通过元对象系统访问的附加特性
在这里插入图片描述

获取/设置属性值

获取

    MyWindow *mw=new MyWindow();mw->show();qInfo()<< mw->property("pos");//结果QVariant(QPoint, QPoint(639,249))

设置

    QObject::connect(btn,&QPushButton::clicked,[&](){auto pos = mw->property("pos").toPoint();mw->setProperty("pos",QPoint(pos.x()-2,pos.y()-2));});

自己声明属性值

要声明属性,请在继承QObject的类中使用Q_PROPERTY()宏

Q_PROPRETY(type name(READ getFunction [WRITE setFunction]|MEMBER memberName [(READ getFunction|WRITE setFunction)])[RESET restFunction][NOTIFY notifySignal][REVISION int | REVISION(int[,int])][DESIGNABLE bool][SCRIPTABLE bool][STORED bool][USER bool][BINDABLE bindableProperty][CONSTANT][FINAL][REQUIRED])

属性的行为类似于数据成员,但它具有通过元对象系统访问的附加特性。

  • 如果未指定MEMBER变量,则需要READ访问器函数。它用于读取属性值。理想情况下,const函数用于此目的,它必须返回属性的类型或对该类型的const引用。例如,QWidget::focus是一个带有READ函数的只读属性,QWidget::hasFocus()。
  • WRITE访问器函数是可选的。它用于设置属性值。它必须返回void并且必须只接受一个参数,该参数可以是属性类型,也可以是指向该类型的指针或引用。例如,QWidget::enabled具有WRITE函数QWidget::setEnabled()。只读属性不需要WRITE函数。例如,QWidget::focus没有Write功能。
  • 如果未指定READ访问器函数,则需要MEMBER变量关联。这使得给定的成员变量可读可写,而无需创建READ和WRITE访问器函数。如果您需要控制变量访问,除了MEMBER变量关联之外,仍然可以使用READ或WRITE访问器函数。
  • RESET功能是可选的。它用于将属性设置回特定于上下文的默认值。
  • NOTIFY信号是可选的。如果已定义,则应指定该类中的一个现有信号,该信号在属性值更改时发出。MEMBER变量的NOTIFY信号必须采用零个或一个参数,该参数必须与属性的类型相同。该参数将采用属性的新值。NOTIFY信号只应在属性真正被更改时发出,以避免在QML中不必要地重新评估绑定。
  • REVISION编号或REVISION()宏是可选的。如果包含,它定义了要在API的特定修订版中使用的属性及其通知信号(通常用于暴露于QML)。如果不包含,则默认为0.
  • DESIGNABLE属性指示该属性是否应在GUI设计工具(如Qt Designer)的属性编辑器中可见。大多数属性是可设计的(默认为true)。有效值为真和假。
  • SCRIPTABLE属性指示脚本引擎是否可以访问此属性(默认为true)。有效值为真和假。
  • STORED属性指示该属性是否应该被认为是独立存在的,或取决于其他值。它还指示在存储对象的状态时是否必须保存属性值。大多数属性值是STORED的(默认为true)。
  • USER属性指示该属性是被指定为该类的面向用户的属性还是用户可编辑的属性。通常,每个类只有一个USER属性(默认false)。
  • BINDABLE bindableProperty属性表明该属性支持绑定,并且可以通过对元对象系统设置和检查该属性的绑定。bindableProperty命名QBindable类型的类成员,其中T是属性类型。
  • CONSTANT属性的存在表明属性值是常量。对于给定的对象实例,常量属性的READ方法在每次调用时都必须返回相同的值。对于对象的不同实例,该常数值可能不同。常量属性不能有WRITE方法或NOTIFY信号。
  • FINAL属性的存在表明该属性不会被派生类覆盖。这在某些情况下可用于性能优化,但并非由moc强制执行。必须注意永远不要覆盖FINAL属性。
  • REQUIRED属性的存在表明该属性应该由该类的用户设置。这不是由moc强制执行的,并且对于暴露给QML的类最有用。在QML中除非设置了所有的REQUIRED属性,否则无法实例化具有REQUIRED属性的类。

#include <QApplication>
#include <QWidget>
#include<QPushButton>
#include<QPointer>class MyWindow:public QWidget
{Q_OBJECTQ_PROPERTY(QString name READ getname WRITE setname NOTIFY nameChanged FINAL)QString m_name;
public:MyWindow(QWidget* parent=nullptr):QWidget(parent){}~MyWindow(){qInfo()<<__FUNCTION__<<"释放了";}
signals:void isShow();void isShow( QString text);
signals:void nameChanged();
public slots:QString getname(){qInfo()<<__FUNCTION__;return m_name;}void setname(QString name){qInfo()<<__FUNCTION__;m_name = name;emit nameChanged();}
public slots:void showWindow(){this->show();emit isShow("我出来了");}void showWindow(bool t){this->close();emit isShow();}
};int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton* btn = new QPushButton("打开");btn->move(10,10);btn->show();MyWindow *mw=new MyWindow();mw->showWindow();QObject::connect(btn,&QPushButton::clicked,[=](){auto pos = mw->property("pos").toPoint();mw->setProperty("pos",QPoint(pos.x()-2,pos.y()-2));mw->setProperty("name","abc");//自定义的name属性改变});QObject::connect(mw,&MyWindow::nameChanged,[&,btn](){auto windowName = mw->property("name");btn->setText(windowName.toString());});return a.exec();
}#include "main.moc"

直接关联也可以

 Q_PROPERTY(QString name  MEMBER m_name NOTIFY nameChanged FINAL)

绑定属性


#include <QApplication>
#include<QProperty>struct Rectangle
{Rectangle() {}int w,h,area;Rectangle(int w,int h):w(w),h(h){area = this->w*this->h;}
};
struct Rect
{Rect() {}QProperty<int> w,h,area;Rect(int w,int h):w(w),h(h){//设置绑定属性area.setBinding([&]{return this->w*this->h;});}
};int main(int argc, char *argv[])
{QApplication a(argc, argv);//没设置绑定属性Rectangle rl(10,10);qInfo()<<rl.area;rl.h =20;qInfo()<<rl.area;//2个结果一样,都是100,没改变//设置绑定属性后Rect r(10,10);qInfo()<<r.area;r.h = 20;qInfo()<<r.area;//结果分别是100,和200return a.exec();
}

QObjectBindableProperty


#include <QApplication>
#include<QProperty>
#include<QWidget>
#include <QPushButton>class MyWindow:public QWidget
{Q_OBJECT
public:MyWindow(QWidget* parent=nullptr):QWidget(parent){}signals:void myxChanged();public:Q_OBJECT_BINDABLE_PROPERTY(MyWindow,int,myx,&MyWindow::myxChanged);};int main(int argc, char *argv[])
{QApplication a(argc, argv);QPushButton* btn = new QPushButton("打开");btn->move(10,10);btn->show();MyWindow* mw = new MyWindow();QObject::connect(btn,&QPushButton::clicked,[=]{static int a=0;mw->show();mw->myx = ++a;});QObject::connect(mw,&MyWindow::myxChanged,[&]{qInfo()<<"x修改了";});return a.exec();
}#include "main.moc"

6.实时类型信息

判断继承自XX类

qInfo()<<mw->inherits("QObject");//true

枚举

#include <QMetaEnum>namespace Yerennuo {
//命名空间
Q_NAMESPACE
enum Type
{Player,Enemy,Bullet
};
//注册枚举
Q_ENUM_NS(Type)
}qInfo()<< Yerennuo::Type::Bullet;//Yerennuo::Bullet

也可以在类里面

class Test:public QObject
{Q_OBJECT
public:enum Type{Player,Enemy,Bullet};Q_ENUM(Type)
};qInfo()<<Test::Type::Player;//Test::Player

QMetaObject元信息


#include "qmetaobject.h"
#include <QApplication>
#include<QWidget>
#include <QMetaObject>class MyWindow:public QWidget
{Q_OBJECTQ_CLASSINFO("author","yerennuo")
public:MyWindow(QWidget* parent=nullptr):QWidget(parent){}};int main(int argc, char *argv[])
{QApplication a(argc, argv);MyWindow* mw = new MyWindow();auto metaobj = mw->metaObject();qInfo()<<"key="<<metaobj->classInfo(0).name()<<"value="<<metaobj->classInfo(0).value();//key= author value= yerennuoreturn a.exec();
}#include "main.moc"

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

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

相关文章

原生小程序开发性能优化指南

性能优化指南 1.骨架屏 业务可以在数据加载完成之前用骨架屏幕来占位&#xff0c;提升体验。 2.包大小优化 减小包中静态资源&#xff0c;例如图片文件&#xff0c;可将图片进行压缩降低文件体积。无用文件、函数、样式剔除。除了部分用于容错的图片必须放在代码包&#xf…

了解游戏相关知识

个人笔记&#xff08;整理不易&#xff0c;有帮助点个赞&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 个人随笔&#xff1a;工作总结随笔_8、以前工作中都接触过哪些类型的测试文档-CSDN博客 目录 一&#xff1a…

MySQL常见故障案例与优化介绍

前言 MySQL故障排查的意义在于及时识别并解决数据库系统中的问题&#xff0c;确保数据的完整性和可靠性&#xff1b;而性能优化则旨在提高数据库系统的效率和响应速度&#xff0c;从而提升用户体验和系统整体性能。这两方面的工作都对于保证数据库系统稳定运行、提升业务效率和…

加域报错:找不到网络路径

在尝试将计算机加入Windows域时&#xff0c;如果收到“找不到网络路径”的错误提示&#xff0c;可能的原因及解决方法如下&#xff1a; 网络连接问题&#xff1a;确保计算机与域控制器之间的物理网络连接是正常的&#xff0c;可以通过ping命令测试与域控制器的连通性。例如&…

LeetCode 56. 合并区间

以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;intervals [[1,3…

HarmonyOS 应用开发之LifecycleService接口切换LifecycleData接口切换

LifecycleService接口切换 FA模型接口Stage模型接口对应d.ts文件Stage模型对应接口onStart?(): void;ohos.app.ability.ServiceExtensionAbility.d.tsonCreate(want: Want): void;onCommand?(want: Want, startId: number): void;ohos.app.ability.ServiceExtensionAbility.…

c# 插值搜索-迭代与递归(Interpolation Search)

给定一个由 n 个均匀分布值 arr[] 组成的排序数组&#xff0c;编写一个函数来搜索数组中的特定元素 x。 线性搜索需要 O(n) 时间找到元素&#xff0c;跳转搜索需要 O(? n) 时间&#xff0c;二分搜索需要 O(log n) 时间。 插值搜索是对实例二分搜索的改进&#xff0c;…

前端 - 基础 表单标签 - 表单元素 input - (name Value checked maxlength )属性详解

目录 name 属性 Value 属性 Checked 属性 Maxlength 属性 场景问答 # <input> 标签 除了 type 属性外&#xff0c;还有其他常用属性 >>> name 属性 在上一节 我们遇到的 单选按钮 &#xff0c;为什么 本应该 多选一 结果成了 多选多的问题 就…

# 达梦数据库知识点

达梦数据库知识点 测试数据 -- SYSDBA.TABLE_CLASS_TEST definitionCREATE TABLE SYSDBA.TABLE_CLASS_TEST (ID VARCHAR(100) NOT NULL,NAME VARCHAR(100) NULL,CODE VARCHAR(100) NULL,TITLE VARCHAR(100) NULL,CREATETIME TIMESTAMP NULL,COLUMN1 VARCHAR(100) NULL,COLUMN…

利用甘特图实现精细化项目管控

在项目管理中,通过精细化管控,项目经理能够有效规划、监督和协调各项任务,从而最大限度控制风险,优化资源配置,并确保按时、按质、按量完成项目目标。而在众多项目管理工具中,甘特图无疑是实现精细化项目管控的利器。zz-plan 是一个非常好用的在线甘特图制作工具&#xff0c;一…

Day78:服务攻防-数据库安全RedisCouchDBH2database未授权访问CVE漏洞

目录 前置知识 数据库应用-Redis-未授权访问&CVE漏洞 未授权访问&#xff1a;CNVD-2015-07557 未授权访问-CNVD-2019-21763 未授权访问-沙箱绕过RCE-CVE-2022-0543 数据库应用-Couchdb-未授权越权&CVE漏洞 Couchdb 垂直权限绕过&#xff08;CVE-2017-12635&…

【操作系统】想要更好的学习计算机,操作系统的知识必不可少!!!

操作系统的概念 导言一、日常生活中的操作系统二、计算机系统层次结构三、操作系统的定义3.1 控制和管理计算机资源3.2 组织、调度计算机的工作与资源的分配3.3 给用户和其他软件提供方便接口与环境3.4 总结 四、操作系统的目标和功能4.1 作为管理者4.1.1 处理机管理4.1.2 存储…

yolov5目标检测可视化界面pyside6源码(无登录版)

一、软件简介&#xff1a; 这是基于yolov5-7.0目标检测实现的的可视化目标检测源码 本套项目没有用户登录的功能&#xff0c;如需用户登录版&#xff0c;看另一篇文章&#xff1a;yolov5pyside6登录用户管理目标检测可视化源码_yolov5用户登入功能-CSDN博客 ①程序中图片和图标…

稳定性生产总结

本期我们来谈下稳定性生产这个话题&#xff0c;稳定性建设目标有两个&#xff1a;降发生、降影响&#xff0c; 在降发生中的措施是做到三点&#xff1a;系统高可用、 高性能、 高质量&#xff0c;三高问题确实是一个很热的话题&#xff0c;里面涉及很多点。 在降影响中要做到…

Windows系统搭建TortoiseSVN客户端并实现无公网IP访问内网服务端

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

Wheel Controller 3D

Wheel Controller 3D是Unity内置WheelCollider的完整替代品。它允许更真实的车辆行为、完全定制和3D地面检测。 Wheel Controller 3D是Unity内置WheelCollider的完整替代品。它允许更真实的车辆行为、完全定制和3D地面检测。 如果您正在寻找包含Wheel Controller 3D的完整车辆物…

路径规划——搜索算法详解(六):LPA*算法详解与Matlab代码

上文讲解了D*算法&#xff0c;D*算法为在动态环境下进行路径规划的场景提出了可行的解决方案&#xff0c;本文将继续介绍另外一种动态规划路径的方法——Lifelong Planning A*&#xff08;LPA*&#xff09;算法。 该算法可以看作是A*的增量版本&#xff0c;是一种在固定起始点…

idea开发 java web 酒店推荐系统bootstrap框架开发协同过滤算法web结构java编程计算机网页

一、源码特点 java 酒店推荐推荐系统是一套完善的完整信息系统&#xff0c;结合java web开发和bootstrap UI框架完成本系统 采用协同过滤算法进行推荐 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式…

萨科微slkor(www.slkoric.com)半导体

萨科微slkor&#xff08;www.slkoric.com&#xff09;半导体技术总监&#xff0c;清华大学李老师介绍说&#xff0c;IGBT器件与MOSFET在技术上的主要区别在于&#xff0c;在IGBT芯片背面引入了一个P掺杂的集电极。从MOSFET拓展至IGBT主要存在IGBT器件设计和IGBT器件加工工艺两方…

Layui三级联动插件使用方法

Layui高版本中没有在提供三级联动这个动画了&#xff0c;而是封装成了一个插件&#xff0c;使用方式也很简单 官网 省市县区三级联动下拉选择器 layarea - Layui 第三方扩展组件平台 (layuion.com)https://dev.layuion.com/extend/layarea/#doc html页面约束 整个选择器需要…