gpt4 book ai didi

Qt - 如何创建随窗口缩放并保持纵横比的图像?

转载 作者:太空狗 更新时间:2023-10-29 11:12:29 24 4
gpt4 key购买 nike

我正在尝试在 QT(内部标签)中创建图像,该图像会根据窗口大小的变化而改变大小,但也会保持纵横比。

最好的方法是什么?

最佳答案

您用 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. 我重载了 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

左边是Max,右边是Moritz。 (反之亦然?)

编辑:

根据 Shefy Gur-ary 的反馈,这在 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)

关于Qt - 如何创建随窗口缩放并保持纵横比的图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42833511/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com