【问题标题】:Qt can I connect signals/slots to self in constructor?Qt 我可以在构造函数中将信号/插槽连接到 self 吗?
【发布时间】:2012-07-23 09:17:03
【问题描述】:

编辑:与信号/插槽/连接无关。问题是构造函数调用构造函数。

可能有更好的方法来做到这一点 - 我很想听听这些......

我有从 QLabel 派生的 MyClass。我想在信号中传递更多关于派生类的数据,而不是基本信号。所以我做了一个槽来拦截 customContextMenuRequested 信号并发出一个有更多数据的修改过的信号。

当我尝试在构造函数中连接这个信号时,我的插槽永远不会被调用。但是,如果我移动策略并将线路连接到父小部件(不是类层次结构父级),以便它们在 MyClass 完全构建后执行,那么我的插槽将被调用。但我总是希望为这个类连接它,这似乎是我想要在它的构造函数中的东西,而不是指望父类记住这样做。

我做错了什么吗?还是向信号添加数据的更好方法?

MyClass::MyClass() : QLabel()
{
    QFont currFont = font();
    currFont.setPointSize(15);
    setFont(currFont);

    setBackgroundRole(QPalette::Mid);

    std::cout << "connecting customContextMenuRequested" << std::endl;
    /** PROBLEM START */
    setContextMenuPolicy(Qt::CustomContextMenu);

    // Is there anything wrong with connecting from "this" to "this" in a constructor?

    QObject::connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
                     this, SLOT(addCellDataToMenuContextRequest(const QPoint&)));
     /* PROBLEM END **/
}


MyClass::MyClass(QString &cellString, int row, int col)
    : QLabel(cellString)
{
    MyClass();
    setRow(row);
    setCol(col);

}

// This one is a slot
void MyClass::addCellDataToMenuContextRequest(const QPoint& pos)
{
        // This doesn't get printed if I connect in my constructor,
        // but it does print if I do the same connect from a parent widget.
    std::cout << "called addCellDataToMenuContextRequest" << std::endl;

    emit customContextMenuRequestedForCell(pos, _row, _col);
}

所以我希望父小部件只查找 customContextMenuRequestedForCell,但现在,父小部件似乎也需要负责 customContextMenuRequested。

【问题讨论】:

  • 根据this question,像这样从另一个构造函数调用一个构造函数是不可行的。你确定那部分工作正常吗?因为否则它对我来说确实很好......
  • 你是对的。我的构造函数调用另一个构造函数是问题所在。我分离到一个初始化文件并且连接工作。谢谢!

标签: c++ qt signals-slots


【解决方案1】:

实际上,如果您使用 C++11,您可以调用(某种程度)另一个构造函数。它被称为delegating constructor。但我认为这不会让问题消失。您的问题似乎是调用 connect() 时元对象未完全构造。此外,您可能需要迁移到 Qt 5 才能使 C++11 正常工作。

解决方案是延迟连接,直到对象完全构建。您可以start a timer 间隔为零。它将在您的对象完全构建之后触发下一个事件循环处理。

然后在您的 timerEvent 中,建立连接并终止计时器。

编辑:没有看到您的编辑。看起来你找到了解决方案。那就忽略这个吧。 :)

顺便说一句。你没有调用另一个构造函数。您创建了一个临时 MyClass 对象。

【讨论】:

    【解决方案2】:

    使这个“更干净”的一种方法是在 MyClass 中重新实现 QWidget::mouseReleaseEvent()。实现它的方法是,如果传递给 mouseReleaseEvent 的 QMouseEvent 类型不是右键单击鼠标释放,则调用 QLabel::mouseReleaseEvent(event)。如果是右键单击鼠标释放事件,您可以发出自定义信号。这提供了使用 QLabel/QWidget 提供的现有鼠标按钮释放处理代码的好处,同时允许您拦截您想要发出自定义信号的一种情况。

    编辑哦,一定要在你的 mouseReleaseEvent 处理自定义案例之后调用 event->accept()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 2014-03-07
      • 2015-03-14
      相关资源
      最近更新 更多