2011-04-13 128 views
25

我已經嘗試了幾種在窗體上顯示圖像的方法,但沒有一種方法符合我的需求。在Qt中顯示圖像以適應標籤尺寸

我讀過很多地方,最簡單的方法是創建一個標籤,並使用它來顯示圖像。我有一個標籤,其大小由佈局指定,但如果我使用像素圖將圖像加載到其中,則標籤將調整爲圖像大小。如果我使用img標籤作爲文本或CSS背景屬性,它將不會顯示整個圖像。我想要做的是將圖像加載到標籤中,而不是更改標籤的大小,但是當我調整窗口大小時,通過重新調整標籤大小,圖像也應該調整大小,以便它始終適合進去。

如果唯一的方法是獲取標籤的大小,並調整其大小以適應像素圖,並處理resize事件(信號),我該如何調整像素大小?我希望我不需要將整個東西保存到QImage中,並且每次都要從中創建一個像素圖。

另外,我該如何居中呢?如果它不適合寬度和高度,我希望較小的尺寸居中。

哦,我不想使用滑塊來處理溢出。

回答

18

請問QLabel::setScaledContents(bool)有幫助嗎? image viewer example也可能有一些有用的信息。

+2

對於一個快速的解決方案,這是一個保護程序,但它通過拉伸圖像(即給了我一個非常難看的結果:沒有保持寬高比)。無論如何,我會將其標記爲解決方案。謝謝。 – SinistraD 2011-04-22 22:44:29

+0

使用PyQt5,此解決方案不起作用。 'setScaledContents'似乎對顯示的圖像大小沒有任何影響。 – ely 2017-05-15 20:40:02

13

我也會回答我自己的問題,但不會將其標記爲解決方案,因爲我請求了上面給出的簡單問題。畢竟,我最終使用的並不是一個簡單的解決方案,所以任何需要做類似工作並有時間去玩的人都可以在這裏找到我的最終工作代碼。這個想法是擴展QLabel並重載setPixmap和drawEvent方法。

QPictureLabel.hpp(頭文件)

#include "QImage.h" 
#include "QPixmap.h" 
#include "QLabel.h" 

class QPictureLabel : public QLabel 
{ 
private: 
    QPixmap _qpSource; //preserve the original, so multiple resize events won't break the quality 
    QPixmap _qpCurrent; 

    void _displayImage(); 

public: 
    QPictureLabel(QWidget *aParent) : QLabel(aParent) { } 
    void setPixmap(QPixmap aPicture); 
    void paintEvent(QPaintEvent *aEvent); 
}; 

QPictureLabel.cpp(實現)

#include "QPainter.h" 

#include "QPictureLabel.hpp" 

void QPictureLabel::paintEvent(QPaintEvent *aEvent) 
{ 
    QLabel::paintEvent(aEvent); 
    _displayImage(); 
} 

void QPictureLabel::setPixmap(QPixmap aPicture) 
{ 
    _qpSource = _qpCurrent = aPicture; 
    repaint(); 
} 

void QPictureLabel::_displayImage() 
{ 
    if (_qpSource.isNull()) //no image was set, don't draw anything 
     return; 

    float cw = width(), ch = height(); 
    float pw = _qpCurrent.width(), ph = _qpCurrent.height(); 

    if (pw > cw && ph > ch && pw/cw > ph/ch || //both width and high are bigger, ratio at high is bigger or 
     pw > cw && ph <= ch || //only the width is bigger or 
     pw < cw && ph < ch && cw/pw < ch/ph //both width and height is smaller, ratio at width is smaller 
     ) 
     _qpCurrent = _qpSource.scaledToWidth(cw, Qt::TransformationMode::FastTransformation); 
    else if (pw > cw && ph > ch && pw/cw <= ph/ch || //both width and high are bigger, ratio at width is bigger or 
     ph > ch && pw <= cw || //only the height is bigger or 
     pw < cw && ph < ch && cw/pw > ch/ph //both width and height is smaller, ratio at height is smaller 
     ) 
     _qpCurrent = _qpSource.scaledToHeight(ch, Qt::TransformationMode::FastTransformation); 

    int x = (cw - _qpCurrent.width())/2, y = (ch - _qpCurrent.height())/2; 

    QPainter paint(this); 
    paint.drawPixmap(x, y, _qpCurrent); 
} 

用法:與使用普通標籤,用於顯示圖像wirthout setScaledContents

img_Result = new QPictureLabel(ui.parent); 
layout = new QVBoxLayout(ui.parent); 
layout->setContentsMargins(11, 11, 11, 11); 
ui.parent->setLayout(layout); 
layout->addWidget(img_Result); 

//{...} 

QPixmap qpImage(qsImagePath); 
img_Result->setPixmap(qpImage); 
+0

很好的回覆,即時只有我的家長小部件的問題,它錯誤 – fredcrs 2012-05-03 19:49:17

+0

它錯誤時,我改變了像素圖和調整大小屏幕 – fredcrs 2012-05-03 20:12:47

+0

這是很久以前(1年對我來說太多了),我甚至沒有Qt安裝了,但我可以幫助。你得到什麼錯誤,在哪一行?你嘗試過調試嗎?或者它是如何「bug」?你可以在這裏做的最好的事情是在這裏發佈一個後續問題在stackoverflow,因此你會得到一個更大的機會從整個用戶基礎的答案。 – SinistraD 2012-05-04 20:09:46

16

實際上這個問題有一個非常簡單的解決方案。有兩件事情你應該修改:

  1. 設置縮放內容爲真(如上所述)
  2. 設置標籤的大小政策忽略

    QLabel lblImage; 
    
    lblImage->setPixmap(QPixmap("big_image.jpg")); 
    
    lblImage->setScaledContents(true); 
    
    lblImage->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); 
    

如果lblImage是在調整圖像將自動延伸至標籤的大小。

+0

我想沒有簡單的解決方案來保持圖像的寬高比? – 2015-05-11 12:11:56

+0

「被忽略」的問題是標籤不能用於「擴展」佈局。 – 2016-06-01 13:56:19

+0

使用PyQt5,這也不行。 'QSizePolicy.Ignored'似乎對圖像是否調整大小沒有影響。 – ely 2017-05-15 20:40:46

6

保留一份原始pixmap的副本。然後連接resized信號到一個槽(或重寫resizeEvent()功能)實現這一點:

lblImage->setPixmap(pixmap.scaled(lblImage->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); 
+0

upvote hard!非常感謝 – 2017-11-24 15:08:05