c++ - Qt/C++ 对扩展 QWidget 的调用函数

标签 c++ qt

在我基于 Qt 的程序中,我有这样的层次结构:

MyApplication::QMainWindow -> QTabWidget -> ProjectWidget::QWidget

在 MyApplication 中,我有一个传统菜单,其中一个操作是导入,需要调用由 QTabWidget->currentWidget 定义的 ProjectWidget->importStuff()。

我遇到的问题是,当我使用 QTabWidget->currentWidget 时,我仅限于 QWidget 函数的子集,我无法调用任何扩展函数。我也不知道如何设置只影响单个 ProjectWidget(不触发其余部分)的 SIGNAL/SLOT

我正在考虑向所有 ProjectWidget 添加一个名为“isCurrent”的属性,然后我将设置一个将调用导入的信号,并检查“isCurrent”状态。如果它是当前小部件,那么它将执行导入功能。但这看起来很复杂,有没有更简单的方法?

最佳答案

你有两个直接的选择

您可以使用 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其他不相关的子类,只有具有相同名称的可调用方法(不是通用父类(super class)方法的重写版本),并且可以调用该方法。无需在编译时提供类定义,无需添加公共(public)基类或引入抽象接口(interface)类并使用多重继承。这基本上就像鸭子打字:if QMetaObject::invokeMethod(ptr, "quack") , 那么它就是一只鸭子。

缺点是没有编译时类型检查,方法名称字符串中的简单拼写错误可能会使代码无提示地失败。因此,重要的是思考(并在代码中实现和注释,并测试)当 invokeMethod 时该怎么做在运行时失败(这是错误,还是某些 UI 状态的正常情况?)。但这适用于(Qt4语法)QObject::connect同样,正如许多 Qt 程序员所经历的那样,当槽因为错别字而没有被调用时 :-)。

关于c++ - Qt/C++ 对扩展 QWidget 的调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19795869/

相关文章:

c++ - 不建议通过 Qt Signals 发出大量数据

c++ - 共享指针谓词;

c++ - std::map 是否分配它的比较器?

c++ - 警告 : control reaches end of non-void function in recursive function

css - 如何设置 Qt 样式表属性的初始值

c++ - 加载 DICOM 图像 Qt C++

c++ - 如何知道何时释放内存?

c++ - float 数据类型错误解释

c++ - 在 Qt 中的两种不同布局中使用相同的小部件

c++ - 每个代理的非平凡 qt 模型数据操作