2015-08-24 23 views
1

編輯3:當我第一次問這個問題時,我以爲是因爲QTimer只發射一次;但事實證明,這是因爲我基於它的remainingTime()成員觀察它。原來實際問題是,remainingTime()倒計數到0只有一次(和timeout()信號確實發射多次)。非單星QTimer只倒計數一次


我有一個單線程Qt應用程序,它有一個需要重複調​​用的計時器。我還有一個進度條來顯示主定時器剩餘的時間,並且進度條每隔40ms由另一個定時器更新一次。

目前,主定時器設置爲15秒(15 x 1000 = 15000毫秒),但定時器僅觸發其一次事件QTimer::timeout()。之後,remainingTime()始終返回0,即使isActive()返回true。 (isSingleShot()回報false,也是如此。)


下面是相關代碼:

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow), 
    interval_capture(15.00), 
    timer_capture(new QTimer(this)), 
    timer_updateProgress(new QTimer(this)), 
    isRecording(false) 
{ 
    ui->setupUi(this); 

    QObject::connect(timer_updateProgress, &QTimer::timeout, 
        this,     &MainWindow::update_progress); 

    // I had to add the following line to force the timer to be called repeatedly 
    //QObject::connect(timer_capture,   &QTimer::timeout, 
    //    timer_capture,   static_cast<void (QTimer::*)()>(&QTimer::start)); 

    timer_capture->setInterval(static_cast<int>(round(interval_capture * 1000))); 
    timer_capture->setSingleShot(false); 
    timer_updateProgress->setInterval(40); 
    timer_updateProgress->setSingleShot(false); 
} 

// -snip- 

void MainWindow::update_progress() 
{ 
    // The math does work 
    double time_passed = 
      static_cast<double>(interval_capture) - 
      static_cast<double>(timer_capture->remainingTime())/1000.0; 
    double fraction_passed = 
      time_passed/static_cast<double>(interval_capture); 
    int percentage = static_cast<int>(round(100 * fraction_passed)); 
    ui->progressBar_timer->setValue(percentage); 

    // I only get an output of "tick: 0" after the first timeout 
    if (timer_capture->isSingleShot() || !timer_capture->isActive()) { 
     ui->progressBar_timer->setFormat("it ded"); 
    } else { 
     ui->progressBar_timer->setFormat("tick: " + QString::number(timer_capture->remainingTime())); 
    } 
} 

// -snip- 

void MainWindow::on_button_start_clicked() 
{ 
    isRecording = !isRecording; 
    switch (isRecording) { 
     case true : 
      ui->button_start->setIcon(QIcon(":/icons/stop.png")); 
      timer_capture->start(); 
      timer_updateProgress->start(); 
      break; 
     case false : 
      ui->button_start->setIcon(QIcon(":/icons/record.png")); 
      timer_capture->stop(); 
      timer_updateProgress->stop(); 
      break; 
    } 
} 

奇怪的是,我知道timer_updateProgress確實工作(因爲我可以看到進度條更新),並以基本相同的方式初始化...


編輯:爲了澄清,我相信,我的所有其他邏輯是正常的,因爲我可以在調試器中看到:

  • timer_capture.isSingleShot()false
  • timer_capture.remainingTime()0
  • timer_capture.isActive()true
  • 所有計算結果都是正確的(例如time_passed

而且我還可以看到,倒計時一次,然後停止。

編輯2:我下面的代碼添加到update_progress()年底進一步說明發生了什麼:

qDebug() << "Active: " << timer_capture->isActive(); 
    qDebug() << "Single shot: " << timer_capture->isSingleShot(); 
    qDebug() << "Remaining ticks:" << timer_capture->remainingTime() << 
       "/" << timer_capture->interval() << "\n"; 

我得到的輸出是:

Active: true 
Single shot: false 
Remaining ticks: 1496/15000 

Active: true 
Single shot: false 
Remaining ticks: 996/15000 

Active: true 
Single shot: false 
Remaining ticks: 494/15000 

Active: true 
Single shot: false 
Remaining ticks: 3/15000 

Active: true 
Single shot: false 
Remaining ticks: 0/15000 

Active: true 
Single shot: false 
Remaining ticks: 0/15000 

(廣告無窮無盡)

+0

你已經註釋掉了timer_capture-> timeout()的插槽。也許'QTimer'實際上沒有做任何事情,如果沒有插槽連接到它?如果它在連接插槽時開始工作,則看起來可能是正在發生的事情。 –

+0

當插槽連接到'&MainWindow :: update_progress()'(未註釋)時,它不起作用,但當它連接到&QTimer :: start()時(如預期的那樣)它可以工作。 我試着將它連接到'update_progress()',因爲這會使它與'timer_updateProgress'基本相同。 –

+0

我明白了。你可以簡化一個計時器,'timer_updateProgress'?只要讓它在每次暫停時增加一個進度條。你是在調試器中運行還是僅僅觀察UI的變化?在調試器中運行會有很大的幫助,所以你可以看到你的計算結果。 –

回答

2

經過一番探索後,我想我找到了答案。問題是,即使QTimer沒有設置爲singleShot,remainingTime的行爲就像它一樣。timeout()信號仍按計劃發射,但在第一個信號後,remainingTime停留在0,而其他一切都發生。

我能夠QObject::connect測試這個荷蘭國際集團的timeout()信號到一個新的slot,叫時pinted到調試流。這表明timeout()被重複調用,而remainingTime停留0

由於這種行爲似乎並不是故意的,我將嘗試使用Qt提交錯誤報告。 (根據記錄,我使用Qt 5.5.0。)


編輯:看來,這是一個已知的bug(46940),將固定的Qt 5.5.1。