【问题标题】:QTimer to execute method every secondQTimer 每秒执行一次方法
【发布时间】:2012-05-20 15:15:32
【问题描述】:

我正在学习 Qt,我正在从 Qt wiki 阅读有关线程、事件和 QObjects 的信息,并遵循 wiki 建议如何在一段时间内处理一些工作,但它不适用于我的具体情况。这是我目前正在努力实现的一个简单示例。

class FooEvents : public FooWrapper {

    public virtual serverTime(..) { std::cout << "Server time event\n"; }
    public virtual connected(..) { std::cout << "Connected event\n"; }
}

class Foo : public QObject {

private:

    FooAPI *client;

public:


    Foo(FooEvents *ev, QObject *parent = 0) : client(new FooApi(ev)) { .. }

private slots:
    void processMessages() {

        if (state is IDLE)              

            reqFooAPiServerTime();

        select(client->fd()+1, ...);

        if (socket is ready for read)

            client.onReceive();

    }
public:
    void connect(...) {

        if (connection) {

            QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(processMessages()));
            timer.start(1000);  // I don't get the output from FooEvents

        }

    }

}

这很简单,但我认为它说明了我的情况。为什么这不起作用以及我必须处理这种情况的其他替代方法?谢谢。s

编辑:processMessages 每秒被调用一次,但我没有从事件中得到任何输出

【问题讨论】:

  • 除非您指定,否则我们无法理解“什么不起作用”!
  • 我看不到 processMessages() 与事件的关系(FooEvents?)
  • @FrankOsterfeld 。它是我正在使用的 API 的一部分。我必须实现 API 提供的所有事件,当我调用 API 方法时,它会通过 FooWrapper 触发相应的事件。
  • @sectorzz9:所以你已经编辑了问题,说processMessage() 每秒都会被调用。在这种情况下,计时器显然没有问题。你需要问一个关于你没有得到“事件的任何输出”的真正问题的问题。这里没有关于您期望什么输出的信息,并且问题的标题与您的实际问题无关(因为该方法每秒执行一次)。

标签: c++ qt qt4


【解决方案1】:

timer 在哪里声明和定义?

如果它是 Foo::connect() 本地的,它会在它有机会开火之前被摧毁。大概它只需要成为Foo 类的成员对象即可。

还请记住,QObject 提供了它自己的简单接口到计时器 - 只需覆盖受保护的虚拟 timerEvent() 函数并调用 QObject 的 startTimer() 即可开始获取这些计时器事件。在这种情况下,它们不会有一个插槽来接收计时器事件,而是会在被覆盖的 timerEvent() 函数处结束:

protected:
    void timerEvent(QTimerEvent *event) {
        processMessages();
    }

public:
    void connect( /* ... */ ) {

            // ... 

            startTimer(1000);
    }

【讨论】:

  • 虽然解决方案是正确的,但我不建议重写 timerEvent()。改用 QTimer,它会使代码更简洁,它是定时器相关操作的专用接口(例如:设置它的参数和控制它)。
  • Viktor:QTimer 有一个额外的 QObject 开销,还有一个额外的信号槽连接。除了明显的内存开销外,直接(非排队)信号槽连接开销在我的机器上等同于将两个 1000 个字符的 QString 连接在一起,所以这不是微不足道的。使用 QBasicTimer 作为 timerId 的占位符和计时器的活动状态是一个不错的优化恕我直言。我个人仅将 QTimer 用于单发,很少触发方便使用。任何周期性的都通过 QBasicTimer 并在QObject::timerEvent() 中处理。
【解决方案2】:

这行不通,因为 processMessages() 不是SLOT

 So Declare processMessages() as a private slot and then try.

【讨论】:

  • 它被定义为一个槽。我忘了把它放在例子中。
  • 然后检查是否进入 if(connection) 块!。
  • 是的。我在编辑消息中说过。 ProcessMessages 每秒被调用一次,但事件没有被触发。如果我直接调用 processMessages 就可以了。
  • 我不小心犯了非插槽错误。所以,即使它不适用于@sectorzz9,这也对我有帮助。
【解决方案3】:

您既不声明计时器也不声明插槽。您必须在标题中声明:

class ... {

  QTimer timer;
  ...
private slots:
  void processMessages();
  ...
};

然后记得建立SIGNAL-SLOT连接并配置定时器:

connect(&timer, SIGNAL(timeout()), this, SLOT(processMessages()));
timer.setInterval(1000);
timer.start();

timer.start(1000); 也是有效的...

另一种可能性

其他可能性是使用与每个 Q_OBJECT 关联的计时器并重载timerEvent

class ... {
  Q_OBJECT
  ...
protected:
  void timerEvent(QTimerEvent *event);
  ...
};

那么你必须像这样实现定时器事件:

void MyClass::timerEvent(QTimerEvent *event) {
  processMessages();
}

您可以通过简单地调用startTimer(1000);来配置计时器

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 2023-03-26
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多