【问题标题】:How to use QTimer to print a message to a QTextBrowser every 10 seconds?如何使用 QTimer 每 10 秒向 QTextBrowser 打印一条消息?
【发布时间】:2011-06-09 08:45:32
【问题描述】:

我已经为此工作了几个小时,无法弄清楚,也找不到任何有效的在线帮助。基本上,我想要完成的要点是拥有一个带有按钮和QTextBrowser 的 Qt GUI。当我按下按钮时,我希望它显示一条消息,然后每 10 秒打印一次此消息。

我想我会使用 QTimer,因为有一个计时器每 10 秒显示一次消息是有意义的。当我最初将它实现到我的 `buttonClicked() SLOT 中时,它导致程序冻结。我在网上寻找解决方案,发现 QApplication::processEvents()。

所以基本上在我的函数中我有这样的东西:

while(1)
{
   QTimer *timer;
   connect(...)  //omitted parameters for this example     
   timer.start(10000);
   ui->diplay->append("Message");

   while(timer.isActive())
   {
      QApplication::processEvents() 
   }
}

我认为它会打破 timer.isActive() while 循环,但它不会简单地停留在那里。

所以我认为这是一个线程问题。所以我想出了如何使用 QThreads 但我仍然无法让它工作。基本上,当我创建一个带有计时器的线程并且线程告诉计时器启动时,程序关闭并且控制台显示“程序意外完成”。

必须有一种简单的方法来做到这一点,但我使用 Qt 的记录一直是这样的

【问题讨论】:

  • 更新:我现在正在使用 timer->singleShot(timer, SIGNAL(timeout()), this, SLOT(update()));但我需要程序打印消息并等待 10 秒,然后才能继续处理。我把它放在一个while循环中,所以它不断地做singleShots而不是每10秒一次。有什么建议?谢谢!
  • 几乎每个人都忽略了这样一个事实,即这是在 while (1) 循环中发生的吗?难怪程序会冻结。

标签: multithreading qt qt4 timer qthread


【解决方案1】:

如果您想在 10 秒内显示您的消息,更好的方法是在您的应用程序中创建一个可以擦除消息的插槽。然后,在您的按钮单击槽中,添加您的消息并初始化一个计时器,该计时器将在 10 秒内触发您的删除消息槽:

QTimer::singleShot(10000, this, SLOT(eraseMessageSlot()));

另外,那里不需要线程......

【讨论】:

  • 我以为我需要线程,因为它冻结了,但显然我的连接不正确。
  • 请在 OP 中查看我的更新。谢谢!
【解决方案2】:

您的代码有很多问题 - 我认为它本质上是伪代码,因为 timer 不存在以及类似的东西。

查看QTimer 参考。它有一个例子:

 QTimer *timer = new QTimer(this);
 connect(timer, SIGNAL(timeout()), this, SLOT(update()));
 timer->start(1000);

基本上,您想创建一个附加的插槽,然后将其连接到timeout 信号并启动计时器。计时器将滴答作响,每一秒都会调用该插槽。在您的情况下,您可以将 1000 更改为 10000

如果这不起作用,您到底遇到了什么问题?我不明白你为什么要使用线程,除非你仍然需要它们。

编辑查看您的更新,您说要等待 10 秒。与其忙着等待,不如继续你的槽中的程序(由singleShot 调用)?我认为你错过了一些 Qt 哲学......

【讨论】:

  • 这基本上是我所拥有的。看来我忘记了“这个参数”并且没有注意到。考虑到我在上面几行使用了带有正确参数的连接语句,这真是太蹩脚了。出于某种原因,编译器并没有对我大喊大叫。
【解决方案3】:

这样组织你的程序会更好:

class MainWindow : QWidget //or any other parent class
{
public:
MainWindow()
{
    QPushButton *button = new QPushButton(this);
    browser_ = new QTextBrowser(this); //and some params maybe
    QVBoxLayout * layout = new QVBoxLayout(this); //can be used another layout
    layout->addWidget(button);
    layout->addWidget(browser_);

    connect(button, SIGNAL(pressed()),
        this, SLOT(onButtonPressed()));

    timer_ = new QTimer(this);
    connect(timer, SIGNAL(timeout()), 
        this, SLOT(timerHandler()));
    }
    ~MainWindow();

public slots:
    void onButtonPressed()
    {
        timerHandler(); //to display message when button is pressed
        if (!timer->isActive()) timer->start(TIMER_INTERVAL); //TIMER_INTERVAL = 10000;
    }
    void timerHandler()
    {
         //put your code to display message here
    }

private:
    QTextBrowser *browser_;
    QTimer *timer_;
}

【讨论】:

  • 这是它在 Qt 中的结构方式。每 10 秒,定时器就会调用 timerHandler 函数。在该函数中,只需附加您的消息并退出该函数。简单直接,最重要的是,没有导致程序死机的无限循环。
  • 我发现 onButtonPressed() 有问题。无论计时器是否处于活动状态,它都会调用 timerHandler()。据我所知,计时器在这里什么都不做,除了在时间过去后自行重置。据我所知,此代码只会在您每次按下按钮时显示消息。
  • 当在插槽 onButtonPressed() 中按下按钮时,定时器被激活;因为 if (!timer->isActive()) timer->start(TIMER_INTERVAL);将被调用
【解决方案4】:

默认情况下,QTimer 将在每个间隔触发,直到您停止它。这就是为什么timer.isActive() 总是正确的。使用timer.setSingleShot(true) 使定时器只触发一次。 (或者在@tibur 的帖子中使用QTimer::singleShot。)

【讨论】:

    【解决方案5】:

    我以为 OP 想要每 10 秒重复显示一次消息?

    在这种情况下,只需创建一个计时器,将 updateDisplay() 函数槽与计时器信号连接并启动计时器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-19
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      相关资源
      最近更新 更多