2017-03-16 252 views
2

我試圖在QT(內部標籤)中創建圖像,根據窗口大小的變化來改變大小,但也會保持寬高比。Qt - 如何創建窗口縮放圖像並保持寬高比?

這樣做的最佳方法是什麼?

+0

請出示您到目前爲止試過的東西。你還會發現['QSize :: scaled'](http://doc.qt.io/qt-5/qsize.html#scaled-1)有用。 –

+0

我嘗試在網格內放置後使用setSizePolicy。但我正在尋找一些有效的東西,而不是修復那些不是很好的東西 –

回答

1

您以linux標記了該問題。我在Windows 10上開發 - 離我最近的Linux是cygwin。因此,我在VS2013中解決了它,但是,嘿,這是C++與Qt。它應該是便攜式的...

實際上,QPixmap::scaled()已經內置了所有必要的功能,通過保持寬高比進行縮放。因此,我的解決方案是將QLabelQPixmap連接在一起。

// standard C++ header: 
#include <iostream> 
#include <string> 

// Qt header: 
#include <QApplication> 
#include <QResizeEvent> 
#include <QLabel> 
#include <QMainWindow> 
#include <QPixmap> 
#include <QTimer> 

using namespace std; 

class LabelImage: public QLabel { 

    private: 
    QPixmap _qPixmap, _qPixmapScaled; 

    public: 
    void setPixmap(const QPixmap &qPixmap) { setPixmap(qPixmap, size()); } 

    protected: 
    virtual void resizeEvent(QResizeEvent *pQEvent); 

    private: 
    void setPixmap(const QPixmap &qPixmap, const QSize &size); 
}; 

void LabelImage::resizeEvent(QResizeEvent *pQEvent) 
{ 
    QLabel::resizeEvent(pQEvent); 
    setPixmap(_qPixmap, pQEvent->size()); 
} 

void LabelImage::setPixmap(const QPixmap &qPixmap, const QSize &size) 
{ 
    _qPixmap = qPixmap; 
    _qPixmapScaled = _qPixmap.scaled(size, Qt::KeepAspectRatio); 
    QLabel::setPixmap(_qPixmapScaled); 
} 

int main(int argc, char **argv) 
{ 
    cout << QT_VERSION_STR << endl; 
    // main application 
#undef qApp // undef macro qApp out of the way 
    QApplication qApp(argc, argv); 
    // setup GUI 
    QMainWindow qWin; 
#if 0 // does not consider aspect ratio 
    QLabel qLblImg; 
    qLblImg.setScaledContents(true); 
#else // (not) 0 
    LabelImage qLblImg; 
#endif // 0 
    qLblImg.setAlignment(Qt::AlignCenter); 
    qLblImg.setSizePolicy(
    QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)); 
    QPixmap qPM; 
    if (qPM.load("cats.jpg")) qLblImg.setPixmap(qPM); 
    else { 
    qLblImg.setText(
     QString::fromLatin1("Sorry. Cannot find file 'cats.jpg'.")); 
    } 
    qWin.setCentralWidget(&qLblImg); 
    qWin.show(); 
    // run application 
    return qApp.exec(); 
} 

注:

  1. 我重載QLabel::setPixmap()方法和實際存儲像素圖的兩個版本 - 原和縮放。我不確定這是否有必要 - 這是我第一次使用QPixmap

  2. 在閱讀Qt文檔時,我發現QLabel::setScaledContents()。我試了一下,但沒有考慮像素圖的長寬比。我無法找到將其設置爲額外選項的方法。 (可能是,我沒有足夠的搜索,我禁用了這個代碼,但留下它來記住這是「錯誤的方向」。)

  3. 在中間版本中,我能夠放大應用程序)但我無法縮小它。谷歌搜索一點點,我發現SO: Enable QLabel to shrink even if it truncates text。這解決了這個問題。

  4. 爲了保持短小的樣本,我對圖像文件名進行了硬編碼。實際上沒必要說應用程序的當前目錄必須是文件所在的目錄。 (這可能是在Linux下沒有問題,但我不得不適當調整在VS2013的調試設置。)

下面是我的測試申請:快照

Snapshot of testQLabelImage.exe

這應該工作(當然)與任何可以加載到Qt中的圖像文件。但是,爲了使樣本完整(並且因爲互聯網和貓的照片真的屬於一起),我還提供了樣本圖像(供下載)。

cats.jpg

左邊是最大,右邊是莫里茨。 (反之亦然?)

編輯:

根據Shefy牛哥元的反饋,這沒有正確的QLayout工作。因此,我修改了原來的版本,並增加了QGridLayout到我的示例代碼來研究這個話題:

// standard C++ header: 
#include <iostream> 
#include <string> 

// Qt header: 
#include <QApplication> 
#include <QGridLayout> 
#include <QGroupBox> 
#include <QLabel> 
#include <QMainWindow> 
#include <QPixmap> 
#include <QResizeEvent> 
#include <QTimer> 

using namespace std; 

class LabelImage: public QLabel { 

    private: 
    QPixmap _qPixmap, _qPixmapScaled; 

    public: 
    void setPixmap(const QPixmap &qPixmap) { setPixmap(qPixmap, size()); } 

    protected: 
    virtual void resizeEvent(QResizeEvent *pQEvent); 

    private: 
    void setPixmap(const QPixmap &qPixmap, const QSize &size); 
}; 

void LabelImage::resizeEvent(QResizeEvent *pQEvent) 
{ 
    QLabel::resizeEvent(pQEvent); 
    setPixmap(_qPixmap, pQEvent->size()); 
} 

void LabelImage::setPixmap(const QPixmap &qPixmap, const QSize &size) 
{ 
    _qPixmap = qPixmap; 
    _qPixmapScaled = _qPixmap.scaled(size, Qt::KeepAspectRatio); 
    QLabel::setPixmap(_qPixmapScaled); 
} 

int main(int argc, char **argv) 
{ 
    cout << QT_VERSION_STR << endl; 
    // main application 
#undef qApp // undef macro qApp out of the way 
    QApplication qApp(argc, argv); 
    // setup GUI 
    QMainWindow qWin; 
    QGroupBox qBox; 
    QGridLayout qGrid; 
    // a macro for the keyboard lazy: 
#define Q_LBL_WITH_POS(ROW, COL) \ 
    QLabel qLbl##ROW##COL(QString::fromLatin1(#ROW", "#COL)); \ 
    /*qLbl##ROW##COL.setFrameStyle(QLabel::Raised | QLabel::Box);*/ \ 
    qGrid.addWidget(&qLbl##ROW##COL, ROW, COL, Qt::AlignCenter) 
    Q_LBL_WITH_POS(0, 0); 
    Q_LBL_WITH_POS(0, 1); 
    Q_LBL_WITH_POS(0, 2); 
    Q_LBL_WITH_POS(1, 0); 
    LabelImage qLblImg; 
    qLblImg.setFrameStyle(QLabel::Raised | QLabel::Box); 
    qLblImg.setAlignment(Qt::AlignCenter); 
    //qLblImg.setMinimumSize(QSize(1, 1)); // seems to be not necessary 
    qLblImg.setSizePolicy(
    QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)); 
    QPixmap qPM; 
    if (qPM.load("cats.jpg")) qLblImg.setPixmap(qPM); 
    else { 
    qLblImg.setText(
     QString::fromLatin1("Sorry. Cannot find file 'cats.jpg'.")); 
    } 
    qGrid.addWidget(&qLblImg, 1, 1, Qt::AlignCenter); 
    qGrid.setRowStretch(1, 1); // tell QGridLayout to stretch this cell... 
    qGrid.setColumnStretch(1, 1); // ...prior to other cells (w/ stretch 0) 
    Q_LBL_WITH_POS(1, 2); 
    Q_LBL_WITH_POS(2, 0); 
    Q_LBL_WITH_POS(2, 1); 
    Q_LBL_WITH_POS(2, 2); 
    qBox.setLayout(&qGrid); 
    qWin.setCentralWidget(&qBox); 
    qWin.show(); 
    // run application 
    return qApp.exec(); 
} 

注:

  1. 圖像的長寬比還是正確的,但調整大小並沒有工作了。因此,我添加了QGrid::setRowStretch()QGrid::setColumnStretch()。不幸的是,這並沒有太大的改變。

  2. 我使用Google搜索這個主題,發現SO: Change resize behavior in Qt layouts。其實,這也沒有幫助,但讓我懷疑QGridLayout可能是這個佈局問題的實際來源。

  3. 爲了更好地理解此佈局問題,我將幀添加到了所有的小部件。令我驚訝的是,它突然出現了。

我認爲在QGridLayout作品的佈局有點不喜歡預期(雖然我不敢說它是錯誤)。但是,圍繞圖像製作框架的解決方法是我可以忍受的。 (事實上​​,它看起來沒有那麼糟糕。)

更新的代碼示例的快照:

Snapshot of testQLabelImage.exe (V2.0)

+0

。花了一些時間讓它工作,但它的作用像魅力。 –

+0

- 您還可以告訴我如何爲另一個容器和佈局中的標籤執行此操作,而不是將其作爲中心控件?找不到辦法。 –

+1

@ ShefyGur-ary剛發現那裏似乎沒有關於回答問題的自動通知。它是這樣的:我更新了我的示例,並且爲'QGridLayout'工作。我想聽聽這是否也適用於Linux端口。 – Scheff

相關問題