我有一个QObject A,它连接到另一个QObject B.现在我希望A连接到C,第三个QObject并完全断开与B.
十分简单!麻烦的是我有很多A都有自己的信号和插槽(B/C更通用).到目前为止,我已经为每个不同的类类型手动创建了connect和disconnect方法.该方法基本上交换彼此的副本connect进行disconnect通话,逆着不要重复自己).
所以我的问题是:以下功能是否可行?
void deleteAllConnections(QObject* someObject) {
// TODO disconnect all connections owned by someObject
// For bonus points: Is there a way of accessing the QMetaObject connected to?
}
Run Code Online (Sandbox Code Playgroud)
我在QMetaObject,QObject以及Signals and Slots文档中捅了一下没有运气(虽然这通常不是保证......).
例如,我有以下课程:
namespace someName
{
class someClass
{
Q_ENUMS(ESomeEnum)
public:
enum ESomeEnum {ENUM_A, ENUM_B, ENUM_C};
// ... some other things ..
}
}
Q_DECLARE_METATYPE(someName::someClass)
Run Code Online (Sandbox Code Playgroud)
有没有办法使用QMetaEnum :: valueToKey或QMetaEnum :: keyToValue?
尝试了这个答案中的方法,但得到以下错误:
Run Code Online (Sandbox Code Playgroud)error: static assertion failed: QMetaEnum::fromType only works with enums declared as Q_ENUM or Q_FLAG #define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)
我可以使用X-Macros来获得我想要的输出,但是在Qt中学习更多技巧也会很好.
有没有办法在给定类名的情况下找到类的QMetaObject实例?我喜欢做的是从磁盘加载对象,但为了实现这一点,我需要一种方法来使用类的名称检索QMetaObject实例,以便使用QMetaObject创建实例.
我有一个后台线程执行任务,完成后,UI 应该更新。要更新 UI,我需要 UI 线程来执行我的函数,其中包含更新 UI 的代码。
Qt 有QMetaObject::invokeMethod((QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr)方法。根据文档,Qt 在创建的线程中调用函子或函数上下文指针,但也可以使用 lambda 来实现(如下所示)。
// QtApplicationWrapper::sApp is of type QGuiApplication
// pFunc - pointer to a function
// pFuncParms - argument of type void *
QMetaObject::invokeMethod (QtApplicationWrapper::sApp,
[=] {
pFunc (pFuncParms);
},
Qt::QueuedConnection);
Run Code Online (Sandbox Code Playgroud)
上面的代码有效。但假设我不想使用 lambda 或函子。
pFunc 可以直接传递给 QMetaObject::invokeMethod ,如下所示:
QMetaObject::invokeMethod (QtApplicationWrapper::sApp,
pFunc,
Qt::QueuedConnection);
Run Code Online (Sandbox Code Playgroud)
但我不知道如何传递参数。上面的代码仅适用于不带参数的函数。
如何在 UI 线程中调用 pFunc 及其参数?
如果我们知道它的类型和名称(如果指定),则可以找到一个孩子,如下所示:
QPushButton *button = parentWidget->findChild<QPushButton *>("button1");
Run Code Online (Sandbox Code Playgroud)
但是,每个函数QObject都有metaObject()返回的函数属性 QMetaObject*。依次QMetaObject具有功能className()。是否可以QObject通过这样的类名轻松找到:
QWidget *widget = (QWidget*)parentWidget->findByClassName("QPushButton", "button1");
Run Code Online (Sandbox Code Playgroud)
或者是让所有QWidget孩子过的唯一方法
QList<QWidget *> widgets = parentWidget->findChildren<QWidget *>("widgetname");
Run Code Online (Sandbox Code Playgroud)
然后std::find_if用metaObject()->className()?过滤列表?
我在CMake项目中遇到了Qt的元对象编译器的问题。我正在构建的共享库包含以下代码,并使用pimpl习惯用法。调用CMake之后,编译后得到
AUTOGEN:错误:〜/ tools / Project / gui / src / mainWindow.cpp:该文件包含Q_OBJECT宏,但不包含“ mainWindow.moc”!gui / CMakeFiles / gui_automoc.dir / build.make:57:目标'gui / CMakeFiles / gui_automoc'的配方制作失败[2]:*** [gui / CMakeFiles / gui_automoc]错误1 CMakeFiles / Makefile2:234:配方目标'gui / CMakeFiles / gui_automoc.dir / all'失败
我没有弄错我的意思,或者是将src文件与Q_OBJECT宏合并到我的项目中的正确方法是什么。请帮助= /
gui / include / gui / mainWindow.hpp
#include <QMainWindow>
#include <string>
class MainWindow : public QMainWindow {
class MainWindowImpl;
public:
MainWindow(QWidget* parent = nullptr);
private:
MainWindowImpl* pimpl_;
};
Run Code Online (Sandbox Code Playgroud)
gui / src / mainWindow.cpp
#include "gui/mainWindow.hpp"
class MainWindow::MainWindowImpl : public QWidget{
Q_OBJECT
public: …Run Code Online (Sandbox Code Playgroud) 我想使用Qt的反射机制,因为C++缺乏这个功能.它似乎工作,但调用所有的宏和辅助函数是非常繁琐的.例如,要将枚举注册为正确的元类型,我必须完成以下所有步骤:
Q_GADGET宏的包装类中声明一个枚举.Q_ENUM之后使用宏注册枚举.Q_DECLARE_METATYPE(MyClass) qRegisterMetaType<..>()包装类的类型和每个声明的枚举.现在我知道如果不需要部分完整功能,可以省略某些步骤.但这不是我想要的,我需要在信号中使用枚举,我需要能够获得信号的元方法并查询它的参数类型.
但我仍然不禁想到必须有更好/更简单的方法来做到这一点.
当调用QMetaMethod::invoke()包含默认参数的方法时,调用失败.
class MyClass : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyClass() : QObject(nullptr){}
public slots:
int MyMethod(int a = 0)
{
return a*2;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass* object = new MyClass();
QMetaObject *metaObject = object->metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
if(metaObject->method(i).name() == "MyMethod")
{
int returnVal;
//returns false
metaObject->method(i).invoke(object,
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
break;
}
}
return a.exec();
}
Run Code Online (Sandbox Code Playgroud)
如果我传递一个int作为第一个参数,那么它运行正常.有没有办法检索方法的参数的默认值,这样我可以传递那些而不是传递任何东西?
我打算在每个方法的类中手动存储默认值,但这是一个丑陋的黑客.
谢谢你的时间.
qmetaobject ×10
qt ×10
c++ ×9
qobject ×3
qt5 ×2
classname ×1
cmake ×1
enums ×1
metadata ×1
qmetatype ×1
qt-signals ×1
qt-slot ×1
qtcore ×1
reflection ×1
templates ×1