【问题标题】:Sending signal from static class method in Qt从 Qt 中的静态类方法发送信号
【发布时间】:2012-03-13 17:54:48
【问题描述】:

我正在尝试编写一个静态回调函数,该函数经常从同一类中的另一个静态函数调用。我的回调函数需要emit 一个信号,但由于某种原因它根本没有这样做。我把它放在调试器下,slot 永远不会被调用。但是,当我将用于emit 的代码放在非静态函数中时,它可以工作。我不能从静态函数发出信号有什么原因吗?我尝试声明一个新的类实例并调用 emit 函数,但没有成功。

class Foo
{
signals:
    emitFunction(int);
private:
    static int callback(int val)
    {
        /* Called multiple times (100+) */
        Foo *foo = new Foo;
        foo.emitFunction(val);
    }
    void run()
    {
        callback(percentdownloaded);
    }
};

我已经发布了一些基本代码来演示我正在尝试做的事情。我会根据要求发布完整的代码。

编辑:我发布了完整的代码,因为这是一种奇怪的情况。 http://pastebin.com/6J2D2hnM

【问题讨论】:

  • 信号和插槽在哪里连接?
  • 我将它们连接到一个单独的.cpp 文件中,该文件在按下按钮时被调用。 void MainWindow::on_pushButton_clicked() { tProc = new Foo(this); connect(tProc, SIGNAL(ValChanged(int)), this, SLOT(onNumberChanged(int))); tProc->start(); } 然后创建我的Foo 类的新实例并启动调用回调函数的线程。
  • 在您的静态回调函数中,您创建一个新的 Foo 实例并在其上调用信号。我想这是你想要发出信号的地方。您如何将此实例连接到您要寻址​​的插槽?
  • 我不完全确定你的意思,但我假设我在 MainWindow::on_pushButton_clicked() 函数中正确连接了它。我需要以某种方式在静态函数中重新连接它吗?
  • clicked 函数中,您将插槽连接到one Foo,但在callback 中,您创建了另一个单独的Foo,它对first foo 一无所知。然后你发出这个新的Foo 的信号,但是新的Foo 的信号没有连接到任何插槽。

标签: c++ qt static callback signals-slots


【解决方案1】:

这是行不通的,因为每次进入该静态函数时都会创建一个新的 Foo,并且不会将信号连接到插槽。

因此,解决方法是将对象传递给该函数:

class Foo
{
signals:
    emitFunction(int);
private:
    static int callback(int val, Foo &foo)
    {
        /* Called multiple times (100+) */
        foo.emitFunction(val);
    }
    void run()
    {
        callback(percentdownloaded, *this);
    }
};

另一种选择是使用postEvent,但我不推荐它。


由于你不能修改回调的签名,你可以这样做:

class Foo
{
signals:
    emitFunction(int);
private:
    static int callback(int val)
    {
        /* Called multiple times (100+) */
        theFoo->emitFunction(val);
    }
    static Foo *theFoo;
    void run()
    {
        callback(percentdownloaded, *this);
    }
};

但您必须在某处初始化该静态变量。

【讨论】:

  • 这会起作用,但问题是我的静态回调函数正被 libCURL 库中的另一个函数调用,我无法向它传递参数。在这种情况下,我不确定如何实现您的方法。
  • @user99545 添加一个静态变量,在回调中使用。我会编辑答案
  • 谢谢。我最终使用了您的静态变量并通过将当前类实例作为参数传递给线程来对其进行初始化。我使用该参数来初始化类并且它起作用了。
  • 非常感谢!我浪费了几个小时试图让它工作,你的第二个建议很棒!
  • @BЈовић 我尝试了第二种方法,但是当我想在承包商中初始化它时,它说未定义对 `Foo ::theFoo' 的引用。
【解决方案2】:

如果有人仍然找到解决方案,这就是我所做的,它适用于我的项目。 1.让你的班级成为单身人士 2.在静态cb函数中,从你的单例类加载emitFunction

    static int callback(int val)
   {
   /* Called multiple times (100+) */
   MYClass::getInstance()->emitFunction(val);
   }

【讨论】:

  • 不错的方法和简单,它甚至是线程安全的,因为信号发射是。 +1
【解决方案3】:

有一个优雅的解决方案。您可以像这样在静态成员函数中发出信号:

emit (instance().newMessage(message));

【讨论】:

    【解决方案4】:

    您必须提供指向类实例的指针才能使其工作。

    但请注意,通常不建议从静态函数发出信号。可以在不创建类实例的情况下调用静态函数,这意味着(如果您不提供发送者作为参数并显式使用它),您将不会拥有用于发出信号的“发送者”对象。

    对于 Lol4t0 建议的这些情况,我也更喜欢回调。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 2011-08-12
      • 1970-01-01
      • 2012-05-11
      • 1970-01-01
      相关资源
      最近更新 更多