在我的基于Qt的程序中,我有一个像这样的层次结构:
MyApplication :: QMainWindow - > QTabWidget - > ProjectWidget :: QWidget的
在MyApplication中,我有一个传统的菜单,其中一个操作是导入,需要调用QWabWidget-> currentWidget定义的ProjectWidget-> importStuff()。
我遇到的问题是当我使用QTabWidget-> currentWidget我只限于QWidget函数的子集时,我无法调用任何扩展函数。我也不知道如何设置一个只影响单个ProjectWidget的SIGNAL / SLOT(不触发其余的)#/ p>
我正在考虑向所有名为“isCurrent”的ProjectWidgets添加一个属性,然后我将设置一个调用import的信号,并检查“isCurrent”状态。如果它是当前小部件,那么它将执行导入功能。但这看起来很复杂,有更简单的方法吗?
答案 0 :(得分:1)
您有两个简单的选择
您可以使用QMetaObject::invokeMethod
静态方法来调用任何可调用的方法,您只需要一个QObject*
指针和方法名称(以及参数,如果有的话)。要使方法可以调用,可以在子类定义中使用Q_INVOKABLE
宏,或者只是将方法放入Qt槽。然后你只需要QObject
指针,并且可以(尝试)使用任何参数调用任何方法(如果不存在这样的方法,则获取错误)。
另一种方法是使用qobject_cast<>()
,它试图将 QObject 子类指针转换为另一个,并返回nullptr
,如果它不能完成(对象不属于该类)。一旦你有正确的指针类型,只需调用你喜欢的任何方法。它与标准C ++ dynamic_cast<>
非常相似,但仅适用于QObject子类,因为它使用Qt元对象系统而不依赖于C ++ RTTI。
注意:当没有很好的方法来使用独立的,与GUI无关的方式来访问窗口小部件时,这两种方式是你应该使用的。但在你的情况下,这些似乎使事情变得如此简单,只要你计划在应用程序的生命周期内保持QTabWidget
,这是合理的。
OP评论的代码示例,使用invokeMethod
方式解决这个问题:
QMetaObject::invokeMethod(myTabWidget->currentWidget(), "callbackFunction");
这有好处,现在可以有两个QObject
子类,这些子类本来是不相关的,只有具有相同名称的invokable方法(不是公共超类方法的覆盖版本),并且该方法可以叫做。没有必要在编译时提供类定义,并且不需要添加公共基类或引入抽象接口类并使用多重继承。这基本上就像鸭子打字:如果是QMetaObject::invokeMethod(ptr, "quack")
,那么它就是鸭子。
接下来是没有编译时类型检查,方法名称字符串中的简单错误可能会使代码无声地失败。因此,当invokeMethod
在运行时失败时(或者是某些UI状态的错误或正常情况?),思考(并在代码中实现和评论,并测试)该做什么很重要。但是这也适用于QObject::connect
的{Qt4语法',因为许多Qt程序员已经学会了很难的方法,当插槽由于输入错误而没有被调用时: - )。