PythonQt简明教程
PythonQt
是Qt框架的Python动态绑定,是一种将Python脚本语言嵌入C++ Qt应用程序的简便方法。与PyQt、PySide不同,PythonQt侧重点在于将Python嵌入到现有的C++应用程序,而不是使用Python编写应用程序。
接口
PythonQt的主要接口通过PythonQt::self()
单例提供,并由PythonQt::init()
初始化。完整的Qt绑定通过PythonQt_QtAll::init()
启用。
数据类型映射
Qt/C++ | Python |
---|---|
bool | bool |
double | float |
float | float |
char/uchar,int/uint,short,ushort,QChar | integer |
long | integer |
ulong,longlong,ulonglong | long |
QString | unicode string |
QByteArray | QByteArray封装器 |
char* | str |
QStringList | unicode字符串元组 |
QVariantList | objects元组 |
QVariantMap | objects字典 |
QVariant | 视类型而定 |
QSize, QRect及其它所有标准Qt变体类型 | 变体封装器,支持对应Qt类完整接口 |
OwnRegisteredMetaType | C++封装器,registerCPPClass提供额外的信息、封装 |
QList<AnyObject*> | 转换为C++封装器列表 |
QVector<AnyObject*> | 转换为C++封装器列表 |
枚举类型 | 枚举封装器 |
QObject (及其子类) | QObject封装器 |
C++对象 | C++封装器,可由PythonQtCppWrapperFactory封装,或由装饰器装饰 |
PyObject | PyObject |
QStringRef
(Qt5)、QStringView
和QAnyStringView
(Qt6)的处理方式与QString
类似QByteArrayView
(Qt6)的处理方式类似于QByteArray
- Python
bytes
类型可以自动转换为QByteArray
。而QByteArray
则通过data()
方法转换为bytes
QVariant
类型将递归映射PyObject
是直接作为指针传递的,这允许将任何Python对象直接传递、返回到使用PyObject *
作为参数、返回值的Qt槽函数
PythonQt实现了所有Qt QVariant类型,并支持这些对象的完整Qt API。
QObject封装
所有在Python解释器中可见的QObject子类,都会自动用一个Python类封装。即
- 调用
PythonQt::addObject
- 槽函数在python中返回一个QObject子类
- 信号函数包含一个QObject子类并连接到python函数
任何在Python可见的QObject子类,除了通过PythonQt::addObject()
添加之外,调用PythonQt::registerClass()
也非常重要。PythonQt::registerClass()
将注册该类完整的父类层次结构,亦即当注册子类时,子类的所有父类都将被注册。
在Python中,不仅可以调用QObject对象的槽函数,还可以访问对象所有的属性。除此之外,还支持:
className()
返回QObject对象类名字符串help()
打印对象的所有属性、槽、枚举、构造函数、封装器槽delete()
删除对象connect(signal, function)
连接信号与python函数connect(signal, qobject, slot)
连接信号与另一QObject对象槽disconnect(signal, function)
断开信号与python函数disconnect(signal, qobject, slot)
断开信号与另一QObject对象槽children()
返回子对象列表setParent(QObject)
设置父对象QObject *parent()
获取父对象
使用信号
# 定义信号处理函数
def someFunction(flag):
print flag
# button1是通过addObject()添加到Python的QPushButton对象
# 连接clicked信号到Python函数
button1.connect("clicked(bool)", someFunction)
定义信号、槽
class MySender(QtCore.QObject):
emitProgress = QtCore.Signal(float) # 此float在C++中对应double
class MyReceiver(QtCore.QObject):
@QtCore.Slot(float)
def progress(self, value):
print(f"progress: {value}")
sender = MySender()
receiver = MyReceiver()
# 通过有效签名连接
sender.connect("emitProgress(double)", receiver, "progress(double)")
sender.emitProgress(2.0)
C++封装
通过如下步骤,实现对C++类的封装:
- 继承QObject并封装C++对象
class CObjectWrapper : public QObject
{
public:
CObjectWrapper(void *object) : object(object) {}
public slots:
// 方法
private:
CObject *object;
};
- 派生
PythonQtCppWrapperFactory
,实现create()
方法
class CObjectFactory : public PythonQtCppWrapperFactory
{
public:
virtual QObject* create(const QByteArray& name, void *ptr)
{
if (name == "CObject")
return new CObjectWrapper(ptr);
return nullptr;
}
};
- 注册工厂
PythonQt::self()->addWrapperFactory(new CObjectFactory);
对于未知的C++类对象,PythonQt将创建一个通用的C++封装器。如果是支持的C++类对象,将通过封装器工厂创建对应的QObject封装器。除此之外,还可以通过装饰器实现。
元对象、元类型
对于每个已知的C++类,PythonQt都提供了对应的Python类,这些类在PythonQt
模块中可见。如果注册类时给出了包名,则在子包中也可见。
元类型支持:
- 访问所有已声明的枚举值
- 构造函数
- 静态方法
- 非绑定非静态方法
help()
和className()
在Python中,可以通过导入PythonQt
模块来访问这些类和Qt命名空间。
from PythonQt import QtCore
# 访问命名空间
print QtCore.Qt.AlignLeft
# 构造函数
a = QtCore.QSize(12,13)
b = QtCore.QFont()
# 静态方法
QtCore.QDate.currentDate()
# 枚举值
QtCore.QFont.UltraCondensed
# 或
QtCore.QFont.Stretch.UltraCondensed
装饰器
装饰器是PythonQt引入的一种扩展封装QObject、C++对象的方法,是提供了具有构造函数、析构函数等功能,并按约定命名的槽函数的QObject子类。
命名约束如下:
- 构造函数
Class *new_Class(Args... args)
- 析构函数
void delete_Class(Class *object)
- 静态方法
ReturnType static_Class_method(Args... args)
- 方法
ReturnType method(Class *object, Args... args)
// C++类实例
class CObject {
public:
CObject(int arg1, float arg2) { a = arg1; b = arg2; }
float method(int arg1) { return arg1 * a * b; };
private:
int a;
float b;
};
// 装饰器实例,可以同时装饰多个C++类
class Decorator : public QObject
{
Q_OBJECT
public slots:
// 构造器
YourCPPObject* new_CObject(int arg1, float arg2) { return new CObject(arg1, arg2); }
// 析构器
void delete_CObject(CObject* obj) { delete obj; }
// 方法
int method(CObject* obj, int arg1) { return obj->method(arg1); }
};
PythonQt::self()->addDecorators(new Decorator());
PythonQt::self()->registerCPPClass("CObject");
from PythonQt import QtCore, QtGui, CObject
# 调用构造函数
object = CObject(1,11.5)
# 调用方法
print object.method(1);
# 调用析构函数
object = None
所有权管理
在PythonQt中,当一个对象由Python构造函数创建是,默认归Python所有;当它从C++接口(如槽)返回时,默认归C++所有。 由于Qt接口中存在各种将所有权传递给其它C++对象的方法,因此PythonQt提供了如下接口来跟踪这些接口调用。
PythonQtPassOwnershipToCPP
传递所有权给C++PythonQtPassOwnershipToPython
传递所有权给PythonPythonQtNewOwnerOfThis
建立新的所有权
这些注解模板适用于所有C++指针类型及QList<AnyObject *>
。
public slots:
PythonQtPassOwnershipToPython<QGraphicsItem*> createNewItemOwnedByPython();
void addItemToCPP(PythonQtPassOwnershipToPython<QGraphicsItem*> item);
void addItemToCPP(PythonQtPassOwnershipToPython<QList<QGraphicsItem*>> items);
void addItemParent(QGraphicsItem* wrappedObject, PythonQtNewOwnerOfThis<QGraphicsItem*> parent);
标签:教程,封装,Python,简明,PythonQt,C++,QObject,CObject
From: https://blog.51cto.com/u_15990474/9102079