2016-08-03 82 views
1

我需要創建一個顯示圖像的簡單GUI,此示例中的圖像可以更改,GUI需要更新其內容。更新Qt圖像在調用exec之前不起作用

我在我的窗口小部件類寫了下面的更新功能:

void myClass::updatePic() { 
    QPixmap pix("./pic.png"); 
    int width = ui->picLabel->width(); 
    int height = ui->picLabel->height(); 
    ui->picLabel->setPixmap(pix.scaled(width,height,Qt::KeepAspectRatio));} 

我嘗試通過以下方式來使用它:

int main(int argc, char *argv[]) { 
QApplication a(argc, argv); 
myClass w; 
w.show(); 

sleep(3); 
w.updatePic(); 

sleep(3); 
w.updatePic(); 

sleep(3); 
return a.exec();} 

但窗口剛打開,並且不顯示圖像直到我們到達a.exec()行,然後打開最後一張圖像。我究竟做錯了什麼?


編輯:

澄清,觸發用於改變圖像來自外部程序(具體地說,GUI將在ROS的節點,並且將另一個節點來觸發)。有沒有一種方法可以通過外部程序從gui中按下按鈕?計時器將工作,但我不喜歡這種「忙等待」風格的解決方案。

感謝您的建議,到目前爲止

回答

2

exec運行QT事件循環,其中包括渲染窗口小部件。

所以將你的電話updatePic到您的小工具,例如通過按鈕或在展示事件

+0

觸發器來自外部程序,QT GUI僅顯示結果並且沒有按鈕。 – user44874

0

功能EXEC也呈現子控件激活它。 exec()阻止應用程序流,而show()不阻止。所以,exec主要用於模態對話框。

我建議使用刷新計時器在自定義智能更新中進行更新。使用QTimer來更新圖像,每3秒:

QTimer* timer = new QTimer(this); 
timer->setInterval(3000); 
connect(timer, SINGAL(timeout()), this, SLOT(updatPicture())); 

更新您的圖片在您的自定義插槽:

MainWindow::updatePicture() { 
    updatePic() 
} 

如果你願意,你可以使用lambda函數:

connect(timer, &QTimer::timeout, this, [&w]() { 
    updatePic() 
}); 
+0

下面是幾乎所有GUI應用程序中都需要的'QApplication :: exec'的討論。你對模態對話意味着什麼? – ilotXXI

1

首先了解更多關於事件循環的內容。尤其是,您必須知道所有事件(例如paintEventresizeEvent)通常都會在相應的事件句柄上調用。事件句柄通常由事件循環調用,即在exec函數中調用。

讓我們聯合@MohaBou和@RvdK的答案。您需要在撥打exec後處理定時器拍攝。爲此使用QObject::timerEvent

myClass::myClass() 
{ 
    <...> 

    // This two variables are members of myClass. 
    _timerId = startTimer(3000); 
    _updatesCount = 0; 
} 

myClass::~myClass() 
{ 
    <...> 

    // For any case. As far as I remember, otherwise the late event 
    // may be handled after the destructor. Maybe it is false, do 
    // not remember... 
    if (_timerId >= 0) { 
     killTimer(_timerId); 
     _timerId = - 1; 
    } 
} 

myClass::timerEvent(QTimerEvent *event) 
{ 
    if (event->timerId() == _timerId) { 
     if (_updatesCount < 2) { 
      updatePic(); 
      ++_updatesCount; 
     } else { 
      killTimer(_timerId); 
      _timerId = - 1; 
     } 
    } 
} 

startTimer方法在這裏增加了特殊的定時器事件的事件查詢每3秒。作爲所有事件,只有在事件循環將控制並處理所有以前的事件時纔可以處理。正因爲如此,如果處理很多「繁重」事件,您可以持續一段時間。

編輯:對不起,我不明白@MohaBou在第一次閱讀。他的答案明確QTimer也足夠好(但我仍然不明白關於形態的一部分)。