您用linux标记了这个问题。我在 Windows 10 上进行开发 - 我手头上最接近 Linux 的是 cygwin。因此,我在 VS2013 中解决了这个问题,但是,嘿,这是带有 Qt 的 C++。应该是便携的...
实际上,QPixmap::scaled()内置了通过保持纵横比进行缩放所需的所有内容。因此,我的解决方案是将QLabel和插入QPixmap在一起的时间相当短。
// 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();
}
Run Code Online (Sandbox Code Playgroud)
笔记:
我重载了该QLabel::setPixmap()方法并实际上存储了像素图的两个版本 - 原始版本和缩放版本。我不确定这是否有必要 - 这是我第一次使用QPixmap。
在阅读 Qt 文档时,我发现了QLabel::setScaledContents()。我尝试了一下,但它没有考虑像素图的纵横比。我找不到将其设置为额外选项的方法。(可能是,我搜索得不够。我禁用了此代码,但将其保留以记住这是“错误的方向”。)
在中间版本中,我能够扩大应用程序(并且缩放效果很好),但我无法缩小它。谷歌搜索了一下,我发现这样:启用 QLabel 收缩,即使它截断文本。这解决了这个问题。
为了使示例简短,我对图像文件名进行了硬编码。其实不用说,应用程序的当前目录一定是该文件所在的目录。(这在 Linux 中可能不是问题,但我必须适当调整 VS2013 中的调试设置。)
下面是我的测试应用程序的快照:
(当然)这应该适用于任何可以加载到 Qt 中的图像文件。然而,为了使示例完整(并且因为互联网和猫的图片确实是一体的),我还提供了示例图像(供下载)。
左边是麦克斯,右边是莫里茨。(或相反亦然?)
编辑:
根据 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();
}
Run Code Online (Sandbox Code Playgroud)
笔记:
图像的长宽比仍然正确,但调整大小不再起作用。因此,我添加了QGrid::setRowStretch()和QGrid::setColumnStretch()。不幸的是,这并没有改变太多。
我用谷歌搜索了这个主题,发现SO: Change resize behavior in Qt layouts。实际上,这也没有什么帮助,但让我怀疑这QGridLayout可能是这个布局问题的实际根源。
为了更好地可视化此布局问题,我向所有小部件添加了框架。令我惊讶的是,它突然起作用了。
我认为作品中的布局QGridLayout在某种程度上与预期不符(尽管我不敢称其为错误)。然而,在图像周围制作框架的解决方法是我可以接受的。(实际上,看起来没那么糟糕。)
更新后的代码示例的快照: