2012-12-04 57 views
2

在一個循環中發射信號我工作的一種視頻播放器,但我有實施問題「播放」功能,其中幀以一定的時間間隔顯示。從QThread的

跳過通過幀使用按鈕或滑塊工作正常,但下面的代碼沒有。此外,它似乎阻止GUI線程,只顯示最後一幀。

void Player::play() 
{ 
    for(int i = currentFrame_; i < replay_->getHeader().numberOfFrames; ++i) 
    { 
     setFrame(i); // load and send frame i 
     msleep(33);  // wait 33 ms 
    } 
} 

void Player::setFrame(int frameNumber) 
{ 
    currentFrame_ = frameNumber; 
    replay_->setCurrentFrame(currentFrame_); // load currentFrame into buffer 
    updateFrame();        // send it to the GUI to be shown 
} 

void Player::updateFrame() 
{ 
    ReplayFrame colorFrame; 

    colorFrame = replay_->getColorFrame(); 
    emit colorFrameEvent(static_cast<unsigned char *>(colorFrame.getData())); // this is connected to MainWindow::showFrame(unsigned char *) 
} 

注意下面的代碼工作正常:

// In main window, called upon loading a replay 
QObject::connect(ui->sliderFrames, SIGNAL(valueChanged(int)), kp, SLOT(setFrame(int))); 

所以移動滑塊實際上並顯示相應的幀。

回答

0

嘛,當然這是發生的......你是在GUI線程,從來沒有得到控制的消息泵在緊張的循環,直到循環結束了! :-)

updateFrame()之後,您可能會同步調用某個更新函數的某種功能,並且您可以觀看播放內容......但是GUI仍然會被凍結w.r.t.您可能想要推送的按鈕(例如「暫停」)

考慮使用計時器代替,所以GUI線程可以運行幀之間的消息泵:

http://doc.qt.digia.com/qt/qtimer.html

+0

的'Player'對象在單獨的線程中運行,所以我的理解是,它會發出' colorFrameEvent'每33毫秒,而在GUI線程之間可以自由地做任何想要的事情。你能解釋一下爲什麼它不會發生? – jaho

+0

自從我開始回答問題以來,您就編輯了您的問題。 :)如果UI被鎖定,那意味着您的GUI泵沒有運行。你確定* Player :: play沒有在GUI線程上運行嗎?你確定你的[線程關聯](http://doc.qt.digia.com/qt/qobject.html#moveToThread)是正確的嗎?通過打印出您正在使用的線程ID來確認事情是否在您期望的線程上運行。 – HostileFork

+1

當然,你是對的。顯然,只有'Player :: run()'方法內部的東西運行在一個單獨的線程中。不知何故,我想到的是調用'球員:: start()方法後'對象將只座位有其線程,並等待來自GUI線程的信號。所以我現在可以把它與另一個工作線程(timer-喜歡),但是我怎麼能這樣做,以便當從GUI發出'on_btnPlay_clicked()'時,'Player :: play()'插槽在單獨的線程中執行?非常感謝。 – jaho