【问题标题】:how to add a 1 second delay using Qtimer如何使用 Qtimer 添加 1 秒延迟
【发布时间】:2013-08-14 15:51:19
【问题描述】:

我目前有一个方法如下

void SomeMethod(int a)
{

     //Delay for one sec.
     timer->start(1000);

     //After one sec
     SomeOtherFunction(a);
}

这个方法实际上是一个附加到信号的槽。我想使用 Qtimer 添加一秒的延迟。但是我不确定如何实现这一点。由于计时器在完成时会触发一个信号,并且该信号需要附加到另一个不接受任何参数的方法。关于我如何完成这项任务的任何建议。?

更新: 该信号将在一秒钟内被多次调用,并且延迟一秒钟。我的问题是将参数传递给附加到计时器的 timeout() 信号的插槽。 我的最后一种方法是将值存储在一个类的成员变量中,然后使用互斥锁来保护它在使用变量时不被更改。但是我在这里寻找更简单的方法。

【问题讨论】:

  • 您是否希望比延迟周期更频繁地处理信号?
  • @Linville 是的,我的延迟是一秒,信号可能在一秒内被多次调用

标签: c++ qt qtimer


【解决方案1】:

实际上,您的问题有一个更优雅的解决方案,不需要成员变量或队列。使用 Qt 5.4 和 C++11 你可以run a Lambda expression right from the QTimer::singleShot(..) method!如果您使用的是 Qt 5.0 - 5.3,您可以使用 connect the QTimer's timeout signal to a Lambda expression 的 connect 方法,该方法将使用适当的参数调用需要延迟的方法。

编辑:在 Qt 5.4 版本中,这只是一行代码!

Qt 5.4(及更高版本)

void MyClass::SomeMethod(int a) {
  QTimer::singleShot(1000, []() { SomeOtherFunction(a); } );
}

Qt 5.0 - 5.3

void MyClass::SomeMethod(int a) {
  QTimer *timer = new QTimer(this);
  timer->setSingleShot(true);

  connect(timer, &QTimer::timeout, [=]() {
    SomeOtherFunction(a);
    timer->deleteLater();
  } );

  timer->start(1000);
}

【讨论】:

  • 这很好。太糟糕了,您不能将 lambda 表达式与静态 QTimer::singleShot() 一起使用。
  • @Roku,同意!这是QTBUG-26406。希望他们能尽快解决这个问题!
  • 另外我没有使用 C++11
【解决方案2】:

我对您提出问题的方式有点困惑,但是如果您询问如何获取计时器的 timeout() 信号以调用带有参数的函数,那么您可以创建一个单独的插槽来接收timeout 然后调用你想要的函数。像这样的东西:-

class MyClass : public QObject
{
    Q_OBJECT
public:
    MyClass(QObject *parent);

public slots:

    void TimerHandlerFunction();
    void SomeMethod(int a);

private:
    int m_a;
    QTimer m_timer;
};

实施:-

MyClass::MyClass(QObject *parent) : QObject(parent)
{
    // Connect the timer's timeout to our TimerHandlerFunction()
    connect(&m_timer, SIGNAL(timeout()), this, SLOT(TimerHandlerFunction()));
}

void MyClass::SomeMethod(int a)
{
    m_a = a; // Store the value to pass later

    m_timer.setSingleShot(true); // If you only want it to fire once
    m_timer.start(1000);
}

void MyClass::TimerHandlerFunction()
{
    SomeOtherFunction(m_a);
}

请注意,QObject 类实际上有一个计时器,您可以通过调用 startTimer() 来使用它,因此您实际上不需要在这里使用单独的 QTimer 对象。将其包含在此处是为了尝试使示例代码接近问题。

【讨论】:

  • 我看到您正在使用类的成员变量并存储参数。但是,这将是多线程的。那么这种方式安全吗?
  • 我只是提醒一下这个解决方案,如果 SomeMethod(..) 的调用速度超过每秒一次,m_a 的值将在使用之前被压缩。
  • 可以,这取决于你如何使用它。如果您在不同的线程中设置和获取成员变量,请确保在设置/获取之前使用 QMutex 锁定它。如果您在线程之间传递值,那么通过信号槽机制执行此操作将确保它是线程安全的。
  • @Linville,非常正确,虽然不知道全部要求,但这可能无关紧要。如果这是一个问题,那么缓存的变量可能是一个整数 QList,每次调用 TimerHandlerFunction 时都会处理它。
  • @ashif 显然,Qtimer 要么需要一个环绕变量的互斥锁,要么需要一个排队连接。我现在只是使用一个线程直接将值传递给它。无论哪种方式,答案都提供了我的选择。谢谢
【解决方案3】:

如果您每秒多次调用 SomeMethod 并且延迟始终恒定,则可以将参数 a 放入 QQueue 并创建一个单次计时器用于调用 @ 987654325@,从QQueue获取参数。

void SomeClass::SomeMethod(int a)
{
    queue.enqueue(a);
    QTimer::singleShot(1000, this, SLOT(SomeOtherFunction()));
}

void SomeClass::SomeOtherFunction()
{
    int a = queue.dequeue();
    // do something with a
}

【讨论】:

    【解决方案4】:

    这不起作用,因为QTimer::start 没有阻塞。

    您应该使用QTimer::singleShot 启动计时器并将其连接到将在QTimer 超时后执行的槽。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-22
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多