Qt:我能在构造函数中连接信号/槽到自身吗?

6

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

可能有更好的方法来解决这个问题 - 我很想听听那些方法...

我有一个从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。


2
根据这个问题,像那样从一个构造函数调用另一个构造函数是不可行的。你确定那部分工作正常吗?否则,它看起来很好... - Xavier Holt
1
你说得对。我的构造函数调用另一个构造函数是问题所在。我将其分离到一个初始化文件中,连接成功了。谢谢! - Steve Hwan
2个回答

5
实际上,如果您使用C++11,您可以(在某种程度上)调用另一个构造函数。它被称为委派构造函数。但我认为这并不能解决问题。您的问题似乎是元对象在调用connect()时没有完全构建。此外,您可能需要升级到Qt 5以使C++11正常工作。
解决方案是延迟连接直到对象完全构建。您可以启动一个间隔为零的定时器。它将在下一个事件循环处理时触发,这肯定会在对象完全构建后发生。
然后在您的timerEvent中进行连接并停止计时器。 编辑:没看到您的编辑。看起来您已经找到了解决方案。请忽略这个。 :)
顺便说一句。您没有调用另一个构造函数。您创建了一个临时MyClass对象。

0
一种使代码更加“清晰”的方法是在MyClass中重新实现QWidget::mouseReleaseEvent()。具体实现方式是,如果传递给mouseReleaseEvent的QMouseEvent类型不是右键鼠标释放事件,则调用QLabel::mouseReleaseEvent(event)。如果是右键鼠标释放事件,则可以发出自定义信号。这样既可以使用QLabel/QWidget提供的现有鼠标按钮释放处理代码,同时又允许你拦截想要发出自定义信号的情况。 编辑 哦,确保在mouseReleaseEvent处理完自定义情况后调用event->accept()。

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