2017-03-16 80 views
2

QT (내부 라벨)에 창 크기의 변경에 따라 크기가 변경되는 이미지를 만들려고하지만 가로 세로 비율도 유지하려고합니다.Qt - 창에 맞게 이미지를 만들고 가로 세로 비율을 유지하는 방법?

가장 좋은 방법은 무엇입니까?

+0

는 지금까지 시도했다 보여주세요. ['QSize :: scaled'] (http://doc.qt.io/qt-5/qsize.html#scaled-1)도 유용 할 것입니다. –

+0

격자 안쪽에 레이아웃을 지정한 후에 setSizePolicy를 사용하여 시도했습니다. 하지만 뭔가 작동하지 않는 것을 고치지 않고 뭔가를 찾고 있습니다. –

답변

1

이 질문에 linux으로 태그를 지정했습니다. 나는 Windows 10에서 개발 - 내가 손에 가지고 리눅스에 가장 가까운 cygwin입니다. 따라서 VS2013에서이 문제를 해결했지만 Qt에서는 C++입니다. 이식성이 있어야합니다.

사실 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. 샘플을 짧게 유지하기 위해 이미지 파일 이름을 하드 코드했습니다. 실제로 응용 프로그램의 현재 디렉토리가 파일이있는 디렉토리 여야한다고 말할 필요는 없습니다. (이것은 리눅스에는 문제는 아마 없을하지만 적절하게 VS2013에서 디버그 설정을 조정해야했다.) 아래는

Snapshot of testQLabelImage.exe

이 작동합니다 내 테스트 APPL :의 스냅 샷입니다 (물론) 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. 저는이 주제를 검색하여 SO: Change resize behavior in Qt layouts을 찾았습니다. 실제로 이것은 도움이되지 않았지만 QGridLayout이이 레이아웃 문제의 실제 출처가 될 수 있다고 생각했습니다.

  3. 이 레이아웃 문제를 더 잘 보여주기 위해 모든 위젯에 프레임을 추가했습니다. 놀랍게도 그것은 갑자기 움직였습니다. (나는 그것을 버그 전화를 감히하지 않을지라도)

은 내가 QGridLayout 작품의 레이아웃은 어떻게 든 예상 좋아하지 않는 것이 가정합니다. 그러나 이미지 주위에 프레임을 만드는 해결 방법은 내가 살 수있는 것입니다. (사실, 그 나쁘지 않아 보인다.)

업데이트 된 코드 샘플의 스냅 샷 :

Snapshot of testQLabelImage.exe (V2.0)

+0

니스. 그것이 작동하도록 내게 시간을 보냈지 만 그것은 매력처럼 작동합니다. –

+0

- 중앙 위젯이 아닌 다른 컨테이너 및 레이아웃 내부의 라벨을 어떻게 처리하는지 알려줄 수 있습니까? 그렇게 할 방법을 찾지 못했습니다. –

+1

@ ShefyGur-ary 방금 답변 한 질문에 대한 자동 알림 기능이없는 것 같습니다. 여기있다 : 나는 내 샘플을 업데이트하고 어떻게 든 QGridLayout을 위해 작업했다. 나는 이것이 리눅스 포트에서도 작동하는지 듣고 싶다. – Scheff