【问题标题】:emit signal with delay延迟发射信号
【发布时间】:2020-10-12 03:48:42
【问题描述】:

我想要实现的目标是发出一个信号,但在实际发出之前将其延迟一段时间。

我的想法是这样的:

emitLater(QObject *obj, QEvent *event, int msDelay)
{
    QTimer...
    connect(timout to obj and event...
    start timer with msDelay...

    //maybe I might need a public timer of some sort but the idea is clear
}

因此,此方法因QEvent 参数而失败,因为信号无法转换为QEvents

我尝试使用 std::bind 调用几个变体,但我无法让它工作:

//the call
std::function<void(void)> signal = std::bind(&CustomPushButton_Header::clicked, &uiWindow->btnHeader_left); //just a random button to connect a valid signal
emitLater(signal, 2000);

//the function
emitLater(std::function<void(void)>, int msDelay)
{
    qDebug() << "hi";
}

我希望有一个适用于所有对象和所有信号的解决方案......也许只是调用该函数的部分。我认为延迟会很容易。

或者你有一个不同的甚至更简单的方法。那就太好了。

我查看的一些来源:

【问题讨论】:

  • 您能否编辑您的问题以提供更完整的用例来显示您想要实现的目标。特别是,显示的代码似乎重用了 QEvent,这将不起作用,因为当控制返回事件循环时,QEvent 将被删除。不过一般来说,如果你有一个函子 f,你想从现在开始调用 ms 毫秒,你可以使用 QTimer::singleShot(ms, f)
  • 哦,是的,这就是我一直在寻找的 :) 谢谢伙计,我现在很开心。您也可以发布解决方案:)

标签: qt parameters signals


【解决方案1】:

有一个函数QTimer::singleShot()可以在一定时间后触发一个信号/槽。我是这样实现的:

void MyWindow::emitLater(const QObject *obj, const char *signalOrSlot, int msDelay)
{
    //use QTimer::singleShot() to trigger the signal/slot after a certain amount of time
    QTimer::singleShot(msDelay, obj, signalOrSlot);
}

并像这样使用它:

void MyWindow::on_pushButton_5_clicked()
{
    //trigger the "doing fancy stuff" function after 5 seconds (= 5000 ms)
    emitLater(this, SLOT(setText()), 5000);
}

void MyWindow::setText()
{
    //do some fancy stuff
    ui->label_3->setText("Hello World!");
}

另一种方法是在 answer from ΦXocę 웃 Пepeúpa ツ 中使用 lambda 表达式作为 QTimer::timout() 信号的调用函数:

void MyWindow::on_pushButton_5_clicked()
{
    //initialize timer
    QTimer* t= new QTimer(this);
    t->setSingleShot(true);

    //do some fancy stuff after timeout
    connect(t, &QTimer::timeout, [this]()
    {
        ui->label_3->setText("Hello World!");
    });

    //start the timer with delay of 5 seconds (= 5000 ms)
    t->start(5000);
}

【讨论】:

    【解决方案2】:

    您可以为此使用计时器,在上面的示例中,您对按钮中的单击槽做出反应,定义一个 QTimer,连接超时时调用的内容(在本例中为 lambda),然后您启动计时器:)

    void MyWindow::on_pushButton_5_clicked()
    {
        QTimer* t= new QTimer(this);
        connect(t, &QTimer::timeout, [this](){ui->label_3->setText("done!");});
        t->start(5000); //after 5 seconds
    }
    

    【讨论】:

    • 是的,这将是一个解决方案。现在我使用QTimer::singleShot(1000, myClass, SLOT(mySlot())),它的效果非常好,而且易于使用。
    • 你能把一个/这个答案标记为答案吗?如果您认为您的解决方案更好,您也可以回答您的 onw 问题:)
    • singleShot() 在这里更好,因为在解决方案中计时器实例会累积,直到 MyWindow 父级被销毁。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    • 2021-08-29
    • 1970-01-01
    相关资源
    最近更新 更多