1.QPixmap::loadFromData導致卡頓
由於項目中需要從網絡上獲取圖片資源,這里用到的方法是QPixmap::loadFromData方法 然后將QPixmap通過setPixmap設置到QLabel中,起初直接在GUI線程中執行着一段代碼,但是發現,一旦開始獲取網絡資源,就會出現無響應現象,剛開始還以為是讀寫造成的,后來通過調試,發現這一步需要消耗大量的時間,最后 我將這個轉換過程寫到一個子線程中,將QByteArray轉換成QPixmap然后通過信號發送出去,GUI線程接收到信號就可以直接操作QPixmap到QLabel中。
1.1 QPixmap不能在子線程中操作,會出現內存錯誤
通過查閱文檔發現, QPixmap跟硬件有關的,專門用於繪制的,因此無法在子線程中操作,圖片資源的讀寫大多數通過QImage來完成,因此上述方法會報錯,轉換了思路,我們將QImage作為數據進行信號傳遞,但仍會報內存錯誤。查閱百度得知,需要進行一次scaled操作,具體原因未知,代碼如下:
if(image.isNull())
{
return;
}
// 注意這里的scaled必須在image上完成,在Pixmap上完成也會報錯
QPixmap mPixmap = QPixmap::fromImage(image.scaled(ui->itemIconLabel->width(), ui->itemIconLabel->height()));
ui->itemIconLabel->setPixmap(mPixmap);
2.錯誤的槽函數綁定導致錯誤
上述操完成之后,程序的卡頓現象確實少了不少,但是程序輸出上面會出現這樣一行字QThread::start: Failed to create thread (xxxxx)
出現這樣的情況,我記錄了子線程調用的次數,結果輸出大吃一驚:當前圖片次數 36100,結果輸出了36000多個線程,結果可想而知,解決這個問題的方法就是減少線程數,知道了肯定是線程調用次數太多了。
通過分析,發現槽函數綁定的問題。一開始我將connect寫在了一個槽函數中,這個槽函數是處理網頁請求得到的數據的,一個網頁基本上有20-30條數據,因此每次執行這個槽函數,都會connect一次,而且是遞歸進行的。所以疊加connect次數才會出現這個數。
// 原程序代碼
void MainWidget::addHomeItem(QWidget *listWidget, HomeItem *homeItem)
{
movieItem* homeMovieItem = new movieItem(this);
homeMovieItem->homeItem = homeItem;
homeMovieItem->setText(homeItem->itemTitle);
homeMovieItem->setNumber(homeItem->itemNumber);
homeMovieItem->setTime(homeItem->itemTime);
listWidget->layout()->addWidget(homeMovieItem);
void *widgetAttribute = (void *)homeMovieItem;
this->homeImgRequest->get(widgetAttribute, QUrl(homeItem->imgPath), true);
// 后來我將這個connect函數放在了構造函數中,連接數減少到了正常
connect(this->homeImgRequest, SIGNAL(dataRequested(void*,QByteArray)), this, SLOT(onReceivedItemImg(void*,QByteArray)));
}
