2016-12-22 28 views
0

我在qt標籤中顯示圖像。下面是我的代碼:在調用函數時獲取Pixmap是一個空像素圖500次

void MyClass::onPushButtonClicked(QString myurl) 
{ 
    this->setCursor(Qt::WaitCursor); 
    ui.qtImageLabel->clear(); 
    qDebug()<<QTime::currentTime()<<"MyClass: onPushButtonClicked"; 
    QNetworkAccessManager *qnam_push_button_clicked_show_image; 
    QNetworkReply *reply; 
    QNetworkRequest request; 
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); 
    QUrl url(myurl); 
    request.setUrl(url); 
    qnam_push_button_clicked_show_image = new QNetworkAccessManager(this); 
    if(qnam_push_button_clicked_show_image) 
    { 
     QObject::connect(qnam_push_button_clicked_show_image, SIGNAL(finished(QNetworkReply*)), 
         this, SLOT(onPushButtonClickedRequestCompleted(QNetworkReply*))); 
     reply = qnam_push_button_clicked_show_image->post(request, url.encodedQuery()); 
     QEventLoop loop; 
     QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); 
     loop.exec(); 
    } 
} 

void MyClass::onPushButtonClickedRequestCompleted(QNetworkReply *reply) 
{ 
    qDebug()<<QTime::currentTime()<<"MyClass: onPushButtonClickedRequestCompleted request completed"; 
    if (reply->error() != QNetworkReply::NoError) 
    { 
     qDebug() << "Error in" << reply->url() << ":" << reply->errorString(); 
     this->setCursor(Qt::ArrowCursor); 
     return; 
    } 
    QByteArray data = reply->readAll(); 
    QPixmap pixmap; 
    pixmap.loadFromData(data); 
    int width; 
    int height; 
    //application size can be changed 
    QRect rec = QApplication::desktop()->screenGeometry(); 
    height = rec.height(); 
    width = rec.width(); 
    qDebug()<<QTime::currentTime()<<width<<","<<height; 
    QSize *size = new QSize(width,height); 
    if(size) 
    { 
     QPixmap scaledPixmap = pixmap.scaled(*size); 
     ui.qtImageLabel->setPixmap(scaledPixmap); 
    } 
    if(size) 
    { 
     delete size; 
     size = NULL; 
    } 
    data.clear(); 
    this->setCursor(Qt::ArrowCursor); 
    reply->deleteLater(); 
    return; 
} 

在點擊按鈕將發送到服務器的請求並顯示從服務器接收到的不同的圖像。如果不超過500次,它工作正常。如果超過第一個這個錯誤已經顯示

QPixmap::scaled: Pixmap is a null pixmap 

並且它不顯示圖像。然後,如果有人再次發送圖像請求,則會顯示以下錯誤: Qt捕獲了事件處理程序引發的異常。在Qt中不支持從事件處理程序中拋出異常事件 。您必須 重新實施QApplication::notify()並在那裏捕獲所有異常。

我沒有得到上面代碼中的錯誤。有人可以告訴我如何解決這個問題嗎?

回答

0

明顯的泄漏是qnam_push_button_clicked_show_image = new QNetworkAccessManager(this);,它在任何地方都沒有均衡的刪除。 QNAM通常應該創建一次,然後在應用程序的整個生命週期中重用,而不是爲單個請求創建。因此,通過在類成員(與ui相同)中啓用qnam_push_button_clicked_show_image,您可以修復泄漏並提高代碼的效率。

這就是說,我不認爲這是什麼原因導致您的QPixmap錯誤。如果您在X11上運行此代碼,那麼QPixmap會受到X Pixmap資源的支持,該資源受各種因素(軟件和硬件)的限制。儘管從你的代碼中沒有明顯的泄漏,但可能是因爲重複分配大的像素映射緩慢地分割由X管理的內存池,直到它不能分配足夠大的縮放像素映射塊爲止,然後觸發錯誤。或者它可能是圖形堆棧中某處的驅動程序錯誤。如果在開始破解之前更改縮放大小增加或減少限制,您是否嘗試過?如果是這樣,切換到QImage可能有助於緩解對X的壓力。

除此之外,代碼可以使用一些清理,特別是多餘的QEventLoop用法。我猜這是一種防止按鈕多次點擊直到新圖片加載完成的方式,但我更願意在圖片下載時使用button.setEnabled(false)來實現這一點,因爲嵌套的事件循環組合在一起網絡事件是無數次重入問題的祕訣,難以調試崩潰/錯誤。

我也搞不清楚爲什麼size是在堆中分配,特別是當它後立即刪除,並且這些if (size)是真正令人困惑,因爲它們可以被理解爲if (size->isValid()),而他們真正的意思是if (size != nullptr),這是非常很大程度上保證了在該線上獲得OOM的機會無限低。 (如果你最終耗盡內存,我的猜測是它可能發生在上面的readAll()或loadFromData()調用中)。

PS:好運按下該按鈕另外500次,檢查固定泄漏幫助;)

+0

噢,還有,當你從'onPushButtonClickedRequestCompleted(QNetworkReply *回覆月初返回)另一個小泄漏'如果'回覆「有錯誤。你在這種情況下不會調用'reply-> deleteLater();'來泄漏回覆。通常這是我在這種插槽中調用的第一件事,這是安全的,因爲直到插槽退出後纔會實際刪除回覆,所以不需要在最後調用它。 –

相關問題