使用宏创建QObject派生类
Using a macro to create QObject derived classes
我试图简化(即摆脱负载的样板代码)QObject
包装器类的创建转发其他QObject
派生类的属性访问。
从小的开始,我只是尝试用一个属性:
// Sy_test.h - The wrapped class
class Sy_test : public QObject
{
Q_OBJECT
Q_PROPERTY( bool prop READ getProp WRITE setProp NOTIFY propChanged )
public:
Sy_test( QObject* parent = nullptr ) :
QObject{ parent },
prop_{ false } {}
bool getProp() const { return prop_; }
public slots:
void setProp( bool value )
{
if ( value != prop_ ) {
prop_ = value;
emit propChanged( prop_ );
}
}
signals:
void propChanged( bool value );
private:
bool prop_;
};
// Sy_proxy.h - The wrapper generator
#define SY_PROXYPROPERTY( Type, Name, Getter, Setter, Notifier )
private:
Q_PROPERTY( Type Name READ Getter WRITE Setter NOTIFY Notifier )
public:
Type Getter() const { return target_->Getter(); }
public slots:
void Setter( Type value ) { target_->Setter( value ); }
signals:
void Notifier( Type value );
private:
void setConnection()
{
connect( target_, &std::remove_pointer< decltype( target_ ) >::type::Notifier,
this, &std::remove_pointer< decltype( this ) >::type::Notifier );
}
#define SY_PROXY( ProxyName, TargetType, Prop1 )
class ProxyName : public QObject
{
Q_OBJECT
Prop1
public:
ProxyName( TargetType* target ) :
target_{ target }
{
setConnection();
}
virtual ~ProxyName() {}
private:
TargetType* target_;
};
// This should create a Sy_test wrapper class called Sy_testProxy
SY_PROXY( Sy_testProxy,
Sy_test,
SY_PROXYPROPERTY( bool, prop, getProp, setProp, propChanged ) )
因此,SY_PROXY
宏应该创建一个名为Sy_testProxy
的类,该类携带Sy_test::prop
属性的副本,其实现仅转发请求/信号。
它几乎做到了。查看后预处理器输出(我使用的是g++,所以是.ii文件),我可以看到构建了Sy_testProxy
类,它与Sy_test
类具有相同的形式。但是,我得到一个错误:
../CppTest/Sy_proxy.h:47: Error: NOTIFY signal 'propChanged' of property 'prop' does not exist in class Sy_testProxy.
make: *** [moc_Sy_proxy.cpp] Error 1
所以它看起来像moc
未能解析我的宏魔术;虽然我不确定SY_PROXY
宏存在的地方(错误来自一个叫做Sy_testProxy
的类),SY_PROXYPROPERTY
也必须是有效的(因为moc
必须从中读取Q_PROPERTY
宏)。有人知道我哪里做错了吗?
声明:我和其他人一样讨厌宏,但由于moc
对模板和QObject
虚拟继承的厌恶,我已经开始使用它们了。之所以触发这项调查,是因为我有一组实例在一个单独的线程中执行繁重的计算,但它们驱动QML表示。然而,QML不允许连接/属性绑定到主线程之外的对象,所以我不得不创建主线程中的代理对象。如果有人有更好的主意,我很乐意接受!
moc
不太喜欢宏。它在一定程度上扩展了它们,但当它们变得复杂时,它就失效了。
你可以尝试用public:
²代替signals:
(即手动扩展signals
宏),并告诉moc你想要的函数是一个信号,把Q_SIGNAL
放在函数声明的前面。
signals:
void Notifier( Type value );
与
public:
Q_SIGNAL void Notifier( Type value );
<子>¹:对于的某些定义,复杂的…我不知道它什么时候会失败,但我过去遇到过一些不同的问题。根据我的经验,我的猜测是,moc有问题,当宏主体包含另一个宏,如signals
在您的例子。但这只是一种猜测——也许moc不擅长的宏是别的什么东西。 子>
<子>²:在Qt 5之前,它曾经是protected
。 子>
除了moc
的变幻莫测之外,您的包装器不是线程安全的。没有从正确的线程调用属性getter。所以我看不出包装纸有什么用。您还不如直接从QML中使用包装类,而不是从包装器中使用。
为了线程安全,您的包装器应该缓存包装属性的值,以便读取总是从本地副本进行。
此时,您不妨编写一个完全动态的包装器,以线程安全的方式从包装对象转发所有属性。使用元对象系统,您可以动态地生成所有内容——属性值的副本,等等。至于属性,您可以复制整个二进制描述符,因为包装器假装具有相同的属性。有一段很好的代码,你可以谷歌qmltricks,它有你需要的一切作为一个好的开始。
你只需要一个标题。有一个扩展的空间来支持只读属性或自定义getter/setter。但我建议你看一看。我找不到真品。页面现在,看到了在上次Qt峰会上的演示,你可能可以检查Qt网站的动手材料。
在github的链接下面,有几个可用的版本。
https://github.com/Cavewhere/lib-qt-qml-tricks/blob/master/include/QQmlHelpers- 为什么使用 "this" 指针调用派生成员函数?
- winapi - 从 QObject 派生类调用时 GetMessage() 崩溃
- 在匿名命名空间中定义QObject派生类
- 如果从 QObject 派生的类的构造函数抛出,则将发出 destroy()
- 为什么QList不是从QObject派生出来的?
- 在Linux上的命令行上编译QObject派生类
- 我应该何时从QObject派生类
- 转储QObject派生对象的所有属性
- 在 QObject 派生类中重复Q_DISABLE_COPY
- 如何重写 QObject::findChildren 以仅返回派生类型
- 定义自己的析构函数,尽管类派生自QObject
- QObject派生的类回调函数到c库
- 使用宏创建QObject派生类
- 如果QObject是从direct派生的,那么使用“虚拟”多重继承是否安全?
- 如何正确使用qRegisterMetaType类派生自QObject
- 在派生的QObject构造函数中连接Qt信号和槽
- 缺少QObject派生类
- 是否有一种方法可以获得QObject派生类的类名而不创建该类的实例化?
- 类与虚函数,当从QObject派生时,导致链接错误
- QList子-从QObject派生的结构或自定义类