【问题标题】:Qt signals & inheritance questionQt信号和继承问题
【发布时间】:2009-05-10 03:23:38
【问题描述】:

我对使用 Qt 编程比较陌生,并且有一个问题。短版:

如何继承超类中定义的信号?

我正在尝试继承别人精心制作的 QTWidgets 以更改一些默认行为:

//Plot3D是一个QWidget,它定义了一个信号“rotationChanged” 类matLinePlot:公共QObject,公共Plot3D { Q_OBJECT; //ETC... 上市: //ETC... //捕捉 Plot3D 的信号“rotationChanged”并用它做一些魔术: 无效初始化图(){ QObject::connect(this, SIGNAL(rotationChanged( double , double , double )), 这,SLOT(myRotationChanged(双,双,双))); } };

问题出在 QObject::connect 行。我想做的是将rotationChanged SIGNAL(来自qwt3D_plot.h)连接到本地函数/SLOT - “myRotationChanged”。但是,每当我这样做时,在运行时我都会得到:

Object::connect: 没有这样的信号 matLinePlot::rotationChanged(double, double, double)

在 C:...\matrixVisualization.h 中。当然,我知道rotationChanged 不在matrixVisualization.h 中——它在qwt_plot3D.h 中,但我认为既然我继承自Plot3D,一切都应该没问题。但是,现在我想起来了,因为 SIGNAL 和 SLOT 是宏,我假设 MOC 不知道/不关心继承。

这引出了我的问题 - 因为 MOC 和 SIGNALS / SLOTS 似乎不了解继承等:我如何子类化在其他地方定义的小部件并访问小部件的信号?

我有很多例子说明如何使用封装来完成这样的事情,但恐怕我不明白如何通过继承来做到这一点。

对不起,如果这是一个荒谬的问题 - 我觉得我错过了一些明显的东西。

【问题讨论】:

  • 您在错误中看到的对“matrixVisualization.h”的引用显示了失败的 QObject::connect 在哪个文件中,而不是它试图“寻找”匹配信号的位置。

标签: qt inheritance subclass signals-slots


【解决方案1】:

我猜问题是多重继承:

class matLinePlot : public QObject, public Plot3D
...

我假设Plot3DQObject 的子类?在这种情况下,你应该这样做

class matLinePlot : public Plot3D
...

改为。

【讨论】:

  • 这使事情变成了一个链接错误:1>moc_matrixVisualization.obj:错误 LNK2001:未解析的外部符号“公共:静态结构 QMetaObject const Qwt3D::Plot3D::staticMetaObject”(?staticMetaObject@Plot3D@Qwt3D @@2UQMetaObject@@B) QT 文档建议使用多重继承:doc.trolltech.com/4.3/uitools-multipleinheritance.html 虽然它们扩展了 QWIdget,但我需要 QObject。
  • 您发布的链接显示了如何使用 .ui 文件(由 Qt Designer 创建的那些文件)的示例。一个重要的区别是 Ui::CalculatorForm 不是 QObject 的子类。从 QObject 子类化(并使用多重继承)时的规则是,只有一个超类可以是 QObject,并且 QObject 必须是继承的第一部分。
  • 文档建议在不同的场景中使用多重继承。使用 Qt Designer 时,您将获得一个 .ui 文件,然后名为 uic 的工具将获取该 .ui 文件并生成一个基本上是 .ui 文件翻译的类,仅在实际 C++ 中。所以他们基本上建议的是从该类继承,而不是将其作为成员。
  • doc.trolltech.com/4.3/moc.html 下,您可以找到有关多重继承的信息。当涉及到编译器错误时,这可能是由于 Plot3D 的头文件中缺少 moc 步骤造成的。
  • ashcatch,这是正确的。谢谢,我不明白 UI 继承和常规继承之间的区别。一旦我与 moc_*.cpp 链接并且也仅从 Plot3D 继承,这工作。
【解决方案2】:

SIGNAL(x) 和 SLOT(x) 是生成字符串文字的宏。在运行时,插槽和信号使用字符串比较这些生成的文字进行匹配。

(我会在 mdec 的评论中添加评论,但我没有足够的代表)

【讨论】:

  • 对 - 我认为这是这个问题的核心;因为匹配 MACRO/MOC 组合的字符串只在当前头文件中查找信号,它不知道在我的其他编译代码库中查找。
  • 皮特,我很确定你错了。信号和槽保存在某处(moc为此生成代码,可以在*_moc文件中看到),与当前头文件无关。
  • (诅咒!-我没有足够的代表添加到皮特关于链接错误的最后评论)看起来你没有在 moc_qwt3D_plot.cpp 中链接。
  • 谢谢丹尼尔和肖恩。我正在链接到 qwtPlot 库,并已包含在我的项目中定义信号的 .h、.cpp 和 moc_.cpp 文件,但仍然没有运气。我认为是因为连接函数正在寻找 matPlotLine::rotationChanged,但实际信号具有签名:
     // SIGNAL 0 void Qwt3D::Plot3D::rotationChanged(double _t1, double _t2, double _t3) 
    在 moc_
    .cpp 文件中
  • Qwt3D 是命名空间吗?你的 matLinePlot 是在同一个命名空间中,还是在某处有 using 指令?
【解决方案3】:

我相信如果 Plot3D::rotationChanged 信号是公开的或受保护的,这将起作用。你确定信号不是私人的吗?

编辑:

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

我还验证了在 QObject 中声明的信号可以在连接语句中使用 QObject 的子类进行连接,因此信号绝对是可继承的。正如我在这里的其他答案和 cmets 中看到的那样,问题一定出在其他地方。

【讨论】:

  • 嗨,我尝试在信号关键字之前放置一个公共关键字,但 Qt MOC 不喜欢这样: 1>MOC include\qwt3d_plot.h 1>include\qwt3d_plot.h(143): 错误:信号不能具有访问说明符 1>项目:错误 PRJ0019:工具从“MOC include\qwt3d_plot.h”返回错误代码
  • 糟糕。显然我应该使用“public:信号:”,但这并没有帮助。
【解决方案4】:

不正确 -> 参见 cmets。

我在 Uni 使用 Qtopia,我相信我记得有人说过关于连接的 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 //has Plot3D class
  • 声明信号时,不要声明参数名称,只声明类型。那是公开的:信号:void rotationChanged(double, double, double);希望这可以解决您的错误。
  • 间距不会影响信号和插槽,您所听到的是信号/插槽规范化,它只是稍微加快了代码速度,但无论如何都很难注意到。
  • 感谢您的澄清 =]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-29
相关资源
最近更新 更多