Qt信号和继承问题

12
我对使用Qt编程相对较新,有一个问题:
如何继承超类中定义的信号?
我试图从别人漂亮制作的QTWidgets进行子类化,以更改一些默认行为:
//Plot3D是一个QWidget,定义了一个名为“rotationChanged”的信号 class matLinePlot : public QObject, public Plot3D {
Q_OBJECT; //etc... public: //etc...
//捕获Plot3D的信号“rotationChanged”,并对其进行一些操作: void initPlot(){ QObject::connect(this, SIGNAL(rotationChanged( double , double , double )), this, SLOT(myRotationChanged(double, double, double))); } };
问题出现在QObject :: connect行中。 我想要做的是将rotationChanged信号(来自qwt3D_plot.h)连接到本地函数/插槽 - “myRotationChanged”。 但是每当我这样做时,在运行时我会得到:
Object :: connect:没有这样的信号matLinePlot :: rotationChanged(double,double,double)
在C:... / matrixVisualization.h中。 当然,我知道rotationChanged不在matrixVisualization.h中-它在qwt_plot3D.h中,但是我认为由于我从Plot3D继承,所以一切都应该没问题。 但是,现在我想一想,由于SIGNAL和SLOT是宏,所以我认为MOC不知道/不关心继承。
这让我想到一个问题——由于MOC和SIGNALS/SLOTS似乎不知道继承等内容:如何从其他地方定义的小部件进行子类化并获得对该小部件信号的访问权限?
我有很多使用封装实现此类操作的示例,但恐怕我不知道如何使用继承来实现。
如果这是一个愚蠢的问题,请原谅我,我觉得我可能忽略了一些显而易见的东西。

1
你所看到的关于 "matrixVisualization.h" 的引用是指出了失败的 QObject::connect 函数所在的文件,而不是它试图寻找匹配信号的位置。 - Idan K
4个回答

10

我猜问题出在多重继承上:

class matLinePlot : public QObject, public Plot3D
...

我假设Plot3DQObject的一个子类? 如果是这样,你应该这样做:

class matLinePlot : public Plot3D
...

改为使用"instead".


1
这会导致链接错误:1>moc_matrixVisualization.obj : error LNK2001: unresolved external symbol "public: static struct QMetaObject const Qwt3D::Plot3D::staticMetaObject" (?staticMetaObject@Plot3D@Qwt3D@@2UQMetaObject@@B)QT文档建议使用多重继承: http://doc.trolltech.com/4.3/uitools-multipleinheritance.html虽然它们扩展了QWIdget,但我需要QObject。 - Pete
2
你发布的链接展示了如何使用.ui文件(这些文件是由Qt Designer创建的)。一个重要的区别是Ui::CalculatorForm不是QObject的子类。当从QObject派生子类(并使用多继承)时,规则是只能有一个父类是QObject,并且QObject必须是继承中的第一个部分。 - ashcatch
1
文档建议在不同的情况下使用多重继承。当使用Qt Designer时,您将获得一个.ui文件,然后一个名为uic的工具将获取该.ui文件并生成一个类,该类基本上是.ui文件的翻译,只不过是实际的C ++。因此,他们基本上建议从该类继承,而不是将其作为成员。 - Idan K
在http://doc.trolltech.com/4.3/moc.html上可以找到关于多重继承的信息。至于编译器错误,这可能是由于您的Plot3D头文件缺少moc步骤引起的。 - ashcatch
ashcatch,这是正确的。谢谢,我之前不理解 UI 继承和普通继承之间的区别。一旦我链接了 moc_*.cpp 文件,并仅从 Plot3D 继承,就可以正常工作了。 - Pete
@ashcatch 只是在更新链接(因为 Trolltech 不再是 Qt 的所有者而中断):https://doc.qt.io/archives/qt-4.8/moc.html - cbuchart

2
SIGNAL(x)和SLOT(x)是生成字符串字面量的宏。在运行时,使用这些生成的字面量字符串进行比较,将slot和signal匹配起来。
(我本想在mdec的评论中添加一条评论,但我的声望不够)

没错 - 我认为这是问题的核心;因为字符串匹配 MACRO/MOC 组合只在当前头文件中查找信号,它不知道要在我编译代码的其他库中查找。 - Pete
Pete,我很确定你是错的。信号和槽被保存在某个地方(moc 生成了此代码,您可以在 *_moc 文件中看到它),这与当前的头文件无关。 - Idan K
看起来你没有链接 moc_qwt3D_plot.cpp。 - sean e
感谢Daniel和Sean。我正在链接qwtPlot库,并在我的项目中包含了.h、.cpp和moc_*.cpp文件,这些文件定义了信号,但仍然没有成功。我认为是因为connect函数正在寻找matPlotLine::rotationChanged,但实际信号的签名为:<pre> // SIGNAL 0 void Qwt3D::Plot3D::rotationChanged(double _t1, double _t2, double _t3) </pre> 在moc_*.cpp文件中。 - Pete
Qwt3D是一个命名空间吗?你的matLinePlot是否在同一个命名空间中,或者你在某个地方使用了using指令? - sean e
是的,我已经解决了命名空间的问题,问题出在a)多重继承和b)链接问题上 - 请参见上文。谢谢。 - Pete

1

我相信如果Plot3D::rotationChanged信号是公共的或受保护的话,那应该可以工作。你确定这个信号不是私有的吗?

编辑:

虽然我找不到具体的参考资料,但我必须得出结论:信号始终是公共的。至少我在这里进行的测试似乎表明,即使在类的私有部分声明了信号,我仍然可以连接到信号。

我还验证了在QObject中声明的信号可以使用QObject的子类在connect语句中连接,因此信号肯定是可继承的。正如我在其他答案和评论中看到的,问题必须在其他地方。


嗨,我尝试在signal关键字之前加上public关键字,但Qt MOC不喜欢那样做:1>MOC include\qwt3d_plot.h 1>include\qwt3d_plot.h(143): Error: 信号不能有访问说明符 1>Project : error PRJ0019: 工具从“MOC include\qwt3d_plot.h”返回了错误代码 - Pete
哎呀,显然我应该使用“public: signals:”,但这并没有帮助。 - Pete

0

错误 -> 请查看注释。

我在大学使用Qtopia,我记得有人说过在connect的SIGNAL和SLOT参数中需要注意间距。

尝试使用

QObject::connect(this, SIGNAL(rotationChanged(double,double,double)),
            this, SLOT(myRotationChanged(double,double,double)));

我知道这似乎不太直观,因为C++对空格不敏感,但我相信这与Qtopia/QT在连接信号和插槽时使用的一些魔法有关。这可能仅适用于Qtopia,或者我可能听错了,但可以尝试一下。此外,信号是公共的还是受保护的,并且您是否已经包含了适当的头文件?


现在我有: 公共的:信号: //! 若旋转被改变,则发出 void rotationChanged(double xAngle,double yAngle,double zAngle); 在头文件和绘图库中,还有QObject::connect(this,SIGNAL(rotationChanged(double,double,double)), this,SLOT(myRotationChanged(double,double,double)));在我的派生类中... 错误仍然存在。我已经包含了头文件: #include <qwt3d_plot.h> //拥有Plot3D类 - Pete
当您声明信号时,不要为参数声明名称,只需指定类型即可。即:public:signals: void rotationChanged(double, double, double);希望这能解决您的错误。 - mdec
间距不会影响信号和槽,你听到的是信号/槽规范化,这只是稍微加速了代码,但那几乎是不可察觉的。 - ismail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接