qt 元对象系统及属性系统

Qt元对象系统(QMetaObject)

Qt 的元对象系统叫 Meta-Object-System,提供了对象之间通信的信号与槽机制、运行时类型信息和动态属性系统。即使编译器不支持RTTI(RTTI的实现耗费了很大的时间和存储空间,这就会降低程序的性能),我们也能动态获取类型信息。

元对象实质上是对类的描述

但是,元对象是基于三个条件的:

 1、该类必须继承自QObject类

 2、必须在类的私有声明区声明Q_OBJECT宏(在类定义的时候,如果没有指定public,

则默认为private,用来启用元对象功能,比如动态属性、信号和槽)。

 3、 元对象编译器Meta-Object Compiler(moc)为 QObject的子类实现元对象

特性提供必要的代码。

有了元对象系统后,我们就可以使用Qt的信号和槽了。

moc(Meta-Object Compiler)元对象预编译器。

moc读取一个c++头文件。如果它找到包含Q_OBJECT宏的一个或多个类声明,它会生成一个包含这些类的元对象代码的c++源文件,并且以moc_作为前缀。

信号和槽机制、运行时类型信息和动态属性系统需要元对象代码。

由moc生成的c++源文件必须编译并与类的实现联系起来。通常,moc不是手工调用的,而是由构建系统自动调用的。

获取类关联的元对象的函数是:metaObject

QMetaObject  *mtobj = QObject::metaObject()

如:

QPushButton *btn=new QPushButton();

const QMetaObject *metaPtr=btn->metaObject();        //获取元对象指针

常用的函数:

(1)函数QMetaObject::className():该函数运行时返回类名称的字符串

(2)函数QObjetc::inhetits()。可以判断一个对象是不是继承自某个类的实例。顶层的父类是QObject ;

(3)函数QMetaObject::superClass()。用来返回该元对象所描述类的父类的元对象,通过父类的元对象可以获取父类的一些元数据;

(4)函数qobject_cast(): 对于Object及其子类对象,可以使用函数qobject_cast()进行动态类型转换,此处可以理解为c++中的强制类型转换

属性系统Q_PROPERTY

在QObject的子类中,使用宏Q_PROPERTY定义属性

Q_PROPERTY(type name

           (READ getFunction [WRITE setFunction] |

            MEMBER memberName [(READ getFunction | WRITE setFunction)])

           [RESET resetFunction]

           [NOTIFY notifySignal]

           [REVISION int]

           [DESIGNABLE bool]

           [SCRIPTABLE bool]

           [STORED bool]

           [USER bool]

           [CONSTANT]

           [FINAL])

Q_PROPERTY()宏定义一个返回值类型为type,名称为name的属性。属性的类型可以是QVarient支持的任何类型( C++标准类型、类名、结构体、枚举等),也可以用户自定义类型。

READ:用于读取属性值。

WRITE:写访问器函数是可选的。用于设置属性值。它必须返回void,并且必须只接受一个参数,要么是属性的类型,要么是指向该类型的指针或引用。

MEMBER:如果未指定读取访问器函数,则需要成员变量关联。这使得给定的成员变量可读写,而无需创建读写访问器函数。使用MEMBER可以替代READWRITE

RESET:复位功能是可选的。它用于将属性设置回其特定于上下文的默认值。

NOTIFY通知信号是可选的。如果已定义,它应该指定该类中的一个现有信号,该信号在属性值更改时发出

定义属性:

头文件:#ifndef COLORMAKER_H#define COLORMAKER_H#include <QObject>class CTest{public:CTest(){}int nAge;QString strName;};Q_DECLARE_METATYPE(CTest)class ColorMaker : public QObject{Q_OBJECTpublic:explicit ColorMaker(QObject *parent = nullptr);~ColorMaker();Q_PROPERTY(int value READ getvalue WRITE setvalue NOTIFY valueChanged);Q_PROPERTY(CTest test READ gettest WRITE settest NOTIFY testChanged);//使用自定义的类int getvalue() const;void setvalue(const int& value);CTest gettest() const;void settest(const CTest& test);signals:void valueChanged(int value);void testChanged(CTest test);private:int m_value;CTest m_test;};#endif // COLORMAKER_H源文件#include "ColorMaker.h"ColorMaker::ColorMaker(QObject *parent){}ColorMaker::~ColorMaker(){}int ColorMaker::getvalue() const{return m_value;}void ColorMaker::setvalue(const int &value){m_value = value;emit valueChanged(m_value);}CTest ColorMaker::gettest() const{return m_test;}void ColorMaker::settest(const CTest &test){m_test = test;emit testChanged(m_test);}

使用属性:

属性的读写既可以使用各个属性自己的读写函数,也可以使用属性通用的函数:setProperty() 写属性,property() 读属性,都是通过属性的名称来寻找特定属性实现读写。

bool setProperty(const char *name, const QVariant &value);

QVariant property(const char *name) const;

setProperty() 第一个参数是普通字符串,就是属性的名称,第二个参数是属性的数值。QVariant 是 Qt 定义的通用变量类型,标准 C++ 的类型和 Qt 自己的数值类型都可以自动转为 QVariant 类的对象。

int propertyCount() const; 通过元对象获取属性的个数

QMetaProperty property(int index) const; 获取属性

QMetaProperty const char *name() const; 获取属性名

例子:

#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include "ColorMaker.h"QT_BEGIN_NAMESPACEnamespace Ui { class Widget; }QT_END_NAMESPACEclass Widget : public QWidget{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public slots:void recv(int nval);void recvtest(CTest test);private:Ui::Widget *ui;};#endif // WIDGET_H源文件#include "widget.h"#include "ui_widget.h"#include <QDebug>#include <QMetaProperty>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);ColorMaker *cm = new ColorMaker();connect(cm,&ColorMaker::valueChanged,this,&Widget::recv);connect(cm,&ColorMaker::testChanged,this,&Widget::recvtest);cm->setvalue(1);int value = cm->getvalue();cm->setProperty("value", 2);value = cm->property("value").toInt();CTest test;test.nAge = 2;test.strName = "qq";cm->setProperty("test",QVariant::fromValue(test));CTest test1 = qvariant_cast<CTest>(cm->property("test"));QObject *object  = cm;const QMetaObject *metaobject = object->metaObject();int ncount = metaobject->propertyCount();for (int i = 0; i < ncount; ++i){QMetaProperty metaproperty = metaobject->property(i);const char *name = metaproperty.name();qDebug() << name;QVariant value = object->property(name);qDebug() << value;}CTest s;s.nAge = 1;s.strName = "hello";QVariant varTest;varTest.setValue(s);QVariant var = QVariant::fromValue(s);bool b = var.canConvert<CTest>();if(b){CTest test = var.value<CTest>();CTest test1 = qvariant_cast<CTest>(var);qDebug() << test.nAge;qDebug() << test.strName;}}Widget::~Widget(){delete ui;}void Widget::recv(int nval){int a = nval;qDebug() << a;}void Widget::recvtest(CTest test){qDebug() << test.nAge;qDebug() << test.strName;}

作用:

  1. 属性系统提供了可以像操作普通的数据成员一样操作这些自定义属性的方法,同时也可以利用Qt的信号槽系统来监听属性值的变化。

使用场景:

  1. Q_PROPERTY用于c++类注册到qml交互上。在c++的变化发送信号,而在qml上接收信号,实现处理槽函数。这个使用于qml导出到c++类,c++类获取和设置qml的属性。
  2. 自定义qt designer 插件 在ui上可以直接看到并设置属性值、信号槽。

延伸:

Q_DECLARE_METATYPE

Q_DECLARE_METATYPE(Type)向Qt元系统注册一些非基本类型。Type可以是自定义类、结构体、枚举。一旦注册后,在Qt元系统中就可以很方便的利用这些非基本类型。

如果Type在命名空间中,Q_DECLARE_METATYPE()必须在命名空间外部。

定义:

class CTest

{

public:

    CTest(){}

    int nAge;

    QString strName;

};

//或者

//struct CTest

//{

//    int nAge;

//    QString strName;

//};

Q_DECLARE_METATYPE(CTest)

使用:

设置函数

QVariant::setValue或者 QVariant fromValue

获取函数

Value 或者 QVariant fromValue

   CTest s;

   s.nAge = 1;

   s.strName = "hello";

   QVariant varTest;

   varTest.setValue(s);

   QVariant var = QVariant::fromValue(s);

   bool b = var.canConvert<CTest>();

   if(b)

   {

       CTest test = var.value<CTest>();

       CTest test1 = qvariant_cast<CTest>(var);

       qDebug() << test.nAge;

       qDebug() << test.strName;

   }

枚举常用宏

 Q_ENUM

作用:宏Q_ENUM会向元对象系统注册一个枚举类型。

使用注意事项:

1.使用Q_ENUM之前,必须在类中先声明Q_OBJECT或Q_GADGET宏。

2.Q_ENUM(枚举类型)必须放在枚举声明之后,放在前面编译器会报错。

如注册Orientation枚举

class Widget : public QWidget

{

    Q_OBJECT

public:

    Widget(QWidget *parent = nullptr);

    ~Widget();

    enum Orientation {

        Up = 1,

        Down = 2,

        Left = 3,

        Right = 4

    };

    Q_ENUM(Orientation)  //向元对象系统注册枚举类型

public slots:

    void recv(int nval);

    void recvtest(CTest test);

private:

    Ui::Widget *ui;

};

使用静态函数QMetaEnum::fromType()来获取QMetaEnum

QMetaEnum metaEnum = QMetaEnum::fromType<Widget::Orientation>(); //MyEnum是当前类,Orientation是枚举的类型

    QMetaEnum metaEnum = QMetaEnum::fromType<Widget::Orientation>();  //通过静态函数fromType获取QMetaEnum对象

    QString name = metaEnum.name();                   //枚举名称

    int count = metaEnum.keyCount();                  //枚举数量

    QString keyIndex = metaEnum.key(0);               //下标为0的key

    int valueIndex = metaEnum.value(0);               //下标为0的value

    QString Key = metaEnum.valueToKey(Widget::Left);  //通过value得到key

    int value = metaEnum.keyToValue("Left");          //通过key得到value

    qDebug() << "枚举的名称:" << name;

    qDebug() << "枚举的数量:" << QString::number(count);

    qDebug() << "index下标的key值:" << keyIndex;

    qDebug() << "index下标的Value值:" << QString::number(valueIndex);                                                                        qDebug() << "value对应的key值:" << Key;

    qDebug() << "key值对应的Vaule:" << QString::number(value);

Q_FLAG

为了解决枚举变量的组合使用,增加枚举变量间与或非计算。且运算结果还是一个QFlags包装的枚举量。一个普通的枚举类型包装成QFlags型,需要使用Q_DECLARE_FLAGS宏,在全局任意地方使用”|"操作符计算自定义的枚举量,需要使用Q_DECLARE_OPERATORS_FOR_FLAGS宏。

Q_DECLARE_FLAGS()宏

Q_DECLARE_FLAGS(Flags, Enum)宏展开为 typedef QFlags<Enum>  Flags;

QFlags<Enum>是一个模板类,其中Enum是枚举类型,QFlags用于存储枚举值的组合

Q_DECLARE_OPERATORS_FOR_FLAGS()

1.Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)赋予了Flags一个全局操作符“|”,没有这个宏语句,Flags量之间进行与操作后的结果将是一个int值,而不是Flags值。

2.Q_DECLARE_OPERATORS_FOR_FLAGS必须定义在类外。

3.Q_DECLARE_OPERATORS_FOR_FLAGS只提供了“或”操作,没有提供“与”“非”操作。

例子

#ifndef WIDGET_H

#define WIDGET_H

#include <QWidget>

#include "ColorMaker.h"

QT_BEGIN_NAMESPACE

namespace Ui { class Widget; }

QT_END_NAMESPACE

class Widget : public QWidget

{

    Q_OBJECT

public:

    Widget(QWidget *parent = nullptr);

    ~Widget();

    enum Orientation {

        Up = 1,

        Down = 2,

        Left = 4,

        Right = 8

    };

    Q_ENUM(Orientation)  //向元对象系统注册枚举类型

    Q_DECLARE_FLAGS(OrientationFlag,Orientation)

    Q_FLAG(OrientationFlag)

public slots:

    void recv(int nval);

    void recvtest(CTest test);

private:

    Ui::Widget *ui;

};

Q_DECLARE_OPERATORS_FOR_FLAGS(Widget::OrientationFlag)

#endif // WIDGET_H

使用

    QMetaEnum metaEnum = QMetaEnum::fromType<Widget::Orientation>();  //通过静态函数fromType获取QMetaEnum对象

    QString name = metaEnum.name();                   //枚举名称

    int count = metaEnum.keyCount();                  //枚举数量

    QString keyIndex = metaEnum.key(0);               //下标为0的key

    int valueIndex = metaEnum.value(0);               //下标为0的value

    QString Key = metaEnum.valueToKey(Widget::Left);  //通过value得到key

    int value = metaEnum.keyToValue("Left");          //通过key得到value

    QString Key2 = metaEnum.valueToKeys(Widget::Left | Widget::Right); //通过value得到key

    int value2 = metaEnum.keysToValue("Up | Down");

    qDebug() << "枚举的名称:" << name;

    qDebug() << "枚举的数量:" << QString::number(count);

    qDebug() << "index下标的key值:" << keyIndex;  //Up

    qDebug() << "index下标的Value值:" << QString::number(valueIndex);  //1

    qDebug() << "value对应的key值:" << Key; //Left

    qDebug() << "value对应的key值:" << Key2; //Left|Right

    qDebug() <<"key值对应的Vaule:"<< QString::number(value);//4

qDebug() <<"key值对应的Vaule:"<< QString::number(value2);//3

QMetaObject::invokeMethod()

作用:使用QMetaObject::invokeMethod()调用QObject的某个注册到元对象系统中的方法。支持跨线程调用。

一般该方法是信号、或者槽函数。无论这个方法是公有的、保护的还是私有的

如果是普通函数,则需要使用Q_INVOKABLE宏把函数注册到元对象系统。

格式:

bool QMetaObjcet:invokeMethod(

QObject* obj,

const char* member,

Qt::ConnectionType type,

QGenericReturnArgument ret,

QGenericReturnArgument  vla0 = QGenericReturnArgument(0),

QGenericReturnArgument  vla1 = QGenericReturnArgument(),

QGenericReturnArgument  vla2 = QGenericReturnArgument(),

QGenericReturnArgument  vla3 = QGenericReturnArgument(),

QGenericReturnArgument  vla4 = QGenericReturnArgument(),

QGenericReturnArgument  vla5 = QGenericReturnArgument(),

QGenericReturnArgument  vla6 = QGenericReturnArgument(),

QGenericReturnArgument  vla7 = QGenericReturnArgument(),

QGenericReturnArgument  vla8 = QGenericReturnArgument(),

QGenericReturnArgument  vla9 = QGenericReturnArgument());

返回值:返回true说明调用成功;返回false,要么是因为没有你说的那个方法,要么是参数类型不匹配;

obj:被调用对象的指针;

member:方法名字   必须是信号、槽,以及Qt元对象系统能识别的类型, 如果不是信号和槽,可以使用qRegisterMetaType()来注册数据类型。此外,使用Q_INVOKABLE来声明函数,也可以正确调用。

type:连接类型;invokeMethod为信号槽而生,你可以指定连接类型,如果被调用的对象和发起调用的线程是同一线程,那么可以使用Qt::DirectConnection、Qt::AutoConnection、Qt::QueuedConnection,如果被调用对象在另一个线程,那么建议使用Qt::QueuedConnection;

ret:接收返回值;

然后就是多达10个可以传递给被调用方法的参数;(看来信号槽的参数个数是有限制的,最好不要超过10个)

QGenericArgument和QGenericReturnArgument是内部帮助程序类,由于可以动态调用信号和槽,因此必须使用Q_ARG()和Q_RETURN_ARG()宏来封装参数

注意:此功能是线程安全的。

例子:

#ifndef COLORMAKER_H#define COLORMAKER_H#include <QObject>class CTest{public:CTest(){}int nAge;QString strName;};Q_DECLARE_METATYPE(CTest)class ColorMaker : public QObject{Q_OBJECTpublic:explicit ColorMaker(QObject *parent = nullptr);~ColorMaker();private slots:QString testslot(int n);};#endif // COLORMAKER_H#include "ColorMaker.h"ColorMaker::ColorMaker(QObject *parent){}ColorMaker::~ColorMaker(){}QString ColorMaker::testslot(int n){return "q";}调用#include "widget.h"//#include "qobjectdefs.h"#include "ui_widget.h"#include <QDebug>#include <QMetaProperty>#include <QMetaObject>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);ColorMaker *cm = new ColorMaker();QString retVal;QMetaObject::invokeMethod(this,"test", Qt::DirectConnection);QMetaObject::invokeMethod(cm,"testslot", Qt::DirectConnection,Q_RETURN_ARG(QString, retVal),Q_ARG(int,1));}void Widget::test(){int a = 1;}

Q_INVOKABLE

作用:定义一个类的成员函数时使用Q_INVOKABLE宏来修饰,就可以让该方法被元对象系统调用(即把该函数注册到元对象系统)。

注意事项:Q_INVOKABLE宏必须放在返回类型前面。

private :

Q_INVOKABLE  QString testmd(int n);

QString ColorMaker::testmd(int n)

{

    return "md";

}

使用场景:

  1. c++和qml混用.

普通类成员函数是不能直接在qml使用。除非是声明为槽函数或者用Q_INVOKABLE声明函数.

  1. 和QMetaObject::invokeMethod()结合使用,invokeMethod函数的参数member方法如果是自定义的普通函数,需使用Q_INVOKABLE宏注册到元对象系统。

例子

class ColorMaker : public QObject{Q_OBJECTpublic:explicit ColorMaker(QObject *parent = nullptr);~ColorMaker();private :Q_INVOKABLE  QString testmd(int n);};ColorMaker *cm = new ColorMaker();QMetaObject::invokeMethod(cm,"testmd", Qt::DirectConnection,Q_RETURN_ARG(QString, retVal),Q_ARG(int,1));

完整代码:

#ifndef COLORMAKER_H#define COLORMAKER_H#include <QObject>class CTest{public:CTest(){}int nAge;QString strName;};Q_DECLARE_METATYPE(CTest)class ColorMaker : public QObject{Q_OBJECTpublic:explicit ColorMaker(QObject *parent = nullptr);~ColorMaker();Q_PROPERTY(int value READ getvalue WRITE setvalue NOTIFY valueChanged);Q_PROPERTY(CTest test READ gettest WRITE settest NOTIFY testChanged);//使用自定义的类int getvalue() const;void setvalue(const int& value);CTest gettest() const;void settest(const CTest& test);signals:void valueChanged(int value);void testChanged(CTest test);private slots:QString testslot(int n);private :Q_INVOKABLE  QString testmd(int n);private:int m_value;CTest m_test;};#endif // COLORMAKER_H#include "ColorMaker.h"ColorMaker::ColorMaker(QObject *parent){}ColorMaker::~ColorMaker(){}int ColorMaker::getvalue() const{return m_value;}void ColorMaker::setvalue(const int &value){m_value = value;emit valueChanged(m_value);}CTest ColorMaker::gettest() const{return m_test;}void ColorMaker::settest(const CTest &test){m_test = test;emit testChanged(m_test);}QString ColorMaker::testslot(int n){return "q";}QString ColorMaker::testmd(int n){return "md";}#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include "ColorMaker.h"QT_BEGIN_NAMESPACEnamespace Ui { class Widget; }QT_END_NAMESPACEclass Widget : public QWidget{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();enum Orientation {Up = 1,Down = 2,Left = 4,Right = 8};Q_ENUM(Orientation)  //向元对象系统注册枚举类型Q_DECLARE_FLAGS(OrientationFlag,Orientation)Q_FLAG(OrientationFlag)public slots:void recv(int nval);void recvtest(CTest test);public slots:void test();private:Ui::Widget *ui;};Q_DECLARE_OPERATORS_FOR_FLAGS(Widget::OrientationFlag)#endif // WIDGET_H#include "widget.h"//#include "qobjectdefs.h"#include "ui_widget.h"#include <QDebug>#include <QMetaProperty>#include <QMetaObject>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget){ui->setupUi(this);QMetaEnum metaEnum = QMetaEnum::fromType<Widget::Orientation>();  //通过静态函数fromType获取QMetaEnum对象QString name = metaEnum.name();                   //枚举名称int count = metaEnum.keyCount();                  //枚举数量QString keyIndex = metaEnum.key(0);               //下标为0的keyint valueIndex = metaEnum.value(0);               //下标为0的valueQString Key = metaEnum.valueToKey(Widget::Left);  //通过value得到keyint value = metaEnum.keyToValue("Left");          //通过key得到valueQString Key2 = metaEnum.valueToKeys(Widget::Left | Widget::Right);  //通过value得到keyint value2 = metaEnum.keysToValue("Up | Down");qDebug() << "枚举的名称:" << name;qDebug() << "枚举的数量:" << QString::number(count);qDebug() << "index下标的key值:" << keyIndex;  //UpqDebug() << "index下标的Value值:" << QString::number(valueIndex);  //1qDebug() << "value对应的key值:" << Key; //LeftqDebug() << "value对应的key值:" << Key2; //Left|RightqDebug() <<"key值对应的Vaule:"<< QString::number(value);//4qDebug() <<"key值对应的Vaule:"<< QString::number(value2);//3ColorMaker *cm = new ColorMaker();QObject *object  = cm;connect(cm,&ColorMaker::valueChanged,this,&Widget::recv);connect(cm,&ColorMaker::testChanged,this,&Widget::recvtest);QString retVal;QMetaObject::invokeMethod(this,"test", Qt::DirectConnection);QMetaObject::invokeMethod(cm,"testslot", Qt::DirectConnection,Q_RETURN_ARG(QString, retVal),Q_ARG(int,1));QMetaObject::invokeMethod(cm,"testmd", Qt::DirectConnection,Q_RETURN_ARG(QString, retVal),Q_ARG(int,1));cm->setvalue(1);int value1 = cm->getvalue();cm->setProperty("value", 2);value = cm->property("value").toInt();CTest test;test.nAge = 2;test.strName = "qq";cm->setProperty("test",QVariant::fromValue(test));CTest test1 = qvariant_cast<CTest>(cm->property("test"));const QMetaObject *metaobject = object->metaObject();int ncount = metaobject->propertyCount();for (int i = 0; i < ncount; ++i){QMetaProperty metaproperty = metaobject->property(i);const char *name = metaproperty.name();qDebug() << name;QVariant value = object->property(name);qDebug() << value;}CTest s;s.nAge = 1;s.strName = "hello";QVariant varTest;varTest.setValue(s);QVariant var = QVariant::fromValue(s);bool b = var.canConvert<CTest>();if(b){CTest test = var.value<CTest>();CTest test1 = qvariant_cast<CTest>(var);qDebug() << test.nAge;qDebug() << test.strName;}}Widget::~Widget(){delete ui;}void Widget::recv(int nval){int a = nval;qDebug() << a;}void Widget::recvtest(CTest test){qDebug() << test.nAge;qDebug() << test.strName;}void Widget::test(){int a = 1;}

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

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

相关文章

URI和URL的区别?

URI&#xff08;Uniform Resource Identifier&#xff0c;统一资源标识符&#xff09;和URL&#xff08;Uniform Resource Locator&#xff0c;统一资源定位符&#xff09;都是网络上用来识别和定位资源的标准方式&#xff0c;但它们之间存在一些差异。 定义: URI 是一个用于…

MongoDB的安装使用

安装MongoDB&#xff08;基于docker安装&#xff09; docker run --restartalways -d --name mongo -v /opt/mongodb/data:/data/db -p 27017:27017 mongo:4.0.6MongoDB的客户端可以从这里下载&#xff08;可能会404&#xff09; https://www.mongodb.com/zh-cn/products/tool…

node.js-fs模块、path模块

fs模块-读写文件 模块&#xff1a;类似插件&#xff0c;封装了方法/属性 fs模块&#xff1a;封装了与本机文件系统进行交互的&#xff0c;方法/属性 语法&#xff1a; 1&#xff09;加载fs模块对象 const fsrequire(fs)//fs 是模块标识符&#xff1a;模块的名字 2&#x…

文献学习-38-用于增量组织病理学分类的内存高效提示调整

​ Memory-Efficient Prompt Tuning for Incremental Histopathology Classification Authors: Yu Zhu, Kang Li, Lequan Yu, Pheng-Ann Heng Source: The Thirty-Eighth AAAI Conference on Artificial Intelligence (AAAI-24) ​​ Abstract 最近的研究在组织病理学分类方面…

Python教学入门:流程控制

条件语句&#xff08;if 语句&#xff09;&#xff1a; 条件语句用于根据条件的真假执行不同的代码块。 x 10if x > 0: # 如果 x 大于 0print("x 是正数") # 输出&#xff1a;x 是正数 elif x 0: # 如果 x 等于 0print("x 是零") else: # 如果以…

Python教程:一文了解Python工厂模式

在软件开发中&#xff0c;一种常见的需求是根据不同条件创建不同类型的对象。工厂模式就是为了解决这个问题而设计的。它提供了一种灵活的方式来创建对象&#xff0c;同时将客户端代码与具体的对象类型解耦&#xff0c;从而使得系统更易于维护和扩展。 1.什么是工厂模式&#x…

Python基于Django的旅游城市关键词分析和提取,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

【Linux系统编程】第五弹---基本指令(三)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、grep指令 2、zip/unzip指令 3、tar指令 4、bc指令 5、uname指令 6、重要的几个热键 7、拓展指令 总结 1、grep指令 …

大屏-flex布局

<div class"container"><div class"title">标题</div><div class"content"><div class"item"></div><div class"item" style"width: calc((100% - 30) / 3 * 2)"><…

C# Solidworks二次开发:程序工具界面和选项相关API详解

大家好&#xff0c;今天要讲的是关于程序工具相关的API介绍。 下面是要介绍的API: (1)第一个为GetAutoPartSimplification&#xff0c;这个API的含义为获取简化配置的指针&#xff0c;下面是官方具体解释&#xff1a; 其输入参数的类型在上一篇文章中已经介绍过了gtError_e&a…

Kimi(月之暗面AI)模型上线,支持长文本输入分析文档内容

国产AI模型目前在市场中正趋于白热化&#xff0c;各大国产AI厂商百花齐放&#xff0c;纷纷优化升级语言模型。近日&#xff0c;备受瞩目的国产AI大模型“月之暗面”也不例外&#xff0c;它对去年10月推出的重量级模型moonshot进行了显著的升级&#xff0c;进一步无损扩展了上下…

(五)C++自制植物大战僵尸游戏LoadingScene的实现讲解

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/xjvbb 一、类介绍 游戏启动后就会立即切换到游戏加载场景中。只有游戏资源文件加载完成后&#xff0c;才能进入游戏。Loadingscene类继承Cocos2d-x中的Scene父类&#xff0c;表明Loadingscene是一个场景类。切换到Loadi…

2024年苹果审核4.3相关问题综述

文章标签&#xff1a;UI、iOS、Objective-C、开发语言 苹果审核中的4.3问题是开发者关注的焦点之一&#xff0c;本文对此进行了综述&#xff0c;总结了不同情况下的处理方式和优化策略。 第一种4.3 该类问题常见于代码或UI的重复率过高&#xff0c;苹果会直接拒绝应用。开发…