2017-03-16 8 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で解決しましたが、ちょっと、これは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. IはQLabel::setPixmap()メソッドをオーバーロードし、実際ピックスマップの2つのバージョンストア - オリジナルとスケーリングを。これが必要なのかどうかはわかりません。QPixmapを初めて使用しました。

  2. Qtドキュメントを読んでいるうちに、QLabel::setScaledContents()が見つかりました。私は試してみましたが、pixmapのアスペクト比は考慮しません。私は余分なオプションとしてこれを設定する方法を見つけることができませんでした。 (このコードを無効にしたが、これを「間違った方向」と覚えておいてください)

  3. 中間バージョンでは、アプリケーションを拡大できました)しかし私はそれを縮小できませんでした。私はちょっとグーグルで見つけたSO: Enable QLabel to shrink even if it truncates text。これは問題を解決しました。

  4. サンプルを短くするために、イメージファイル名をハードコードしました。実際には、アプリケーションの現在のディレクトリは、ファイルが置かれているディレクトリでなければならないとは言いません。以下は、(これはおそらく、Linuxのには問題ありませんが、私は適切にVS2013でのデバッグ設定を調整する必要がありました。)

私のテストAPPLのスナップショットです。:

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

関連する問題