C++ 如何使图像调整大小以在 Qt 中缩放?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14107144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I make an image resize to scale in Qt?
提问by chacham15
I made a class called ImageLabel which extends QLabel. I want it to keep the size ratio of the image that it is displaying no matter how stretched out it is. It works fine when you make the window larger. The problem comes in when you try to make the window smaller: it doesnt resize the height, it leaves it stretched out. How do I fix this?
我创建了一个名为 ImageLabel 的类,它扩展了 QLabel。我希望它保持它显示的图像的大小比例,无论它有多拉伸。当您使窗口变大时,它工作正常。当您尝试使窗口变小时,问题就出现了:它不会调整高度的大小,而是将其拉伸。我该如何解决?
int ImageLabel::heightForWidth(int width) const {
int height = (this->size.height()*width)/this->size.width();
return height;
}
QSize ImageLabel::sizeHint() const {
return this->size;
}
QSize ImageLabel::minimumSizeHint() const {
return QSize(0, 0);
}
void ImageLabel::setSizePolicy(){
QSizePolicy policy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
policy.setHeightForWidth(true);
QLabel::setSizePolicy(policy);
QLabel::setScaledContents(true);
}
void ImageLabel::setPixmap ( const QPixmap &pixmap ){
this->size = pixmap.size();
QLabel::setPixmap(pixmap);
}
int main(int argc, char *argv[]){
QApplication a(argc, argv);
QFrame *frame = new QFrame;
QVBoxLayout *layout = new QVBoxLayout;
frame->setLayout(layout);
QPixmap map;
map.load("test.png");
ImageLabel *label = new ImageLabel;
label->setSizePolicy();
label->setPixmap(map);
layout->addWidget(label);
frame->show();
return a.exec();
}
回答by jdi
There are a couple ways to do this, but most of all I would recommend maybe not fighting against the layout system by trying to hint the aspect. As you can see, you are having to try and implement a number methods trying to help the layout.
有几种方法可以做到这一点,但最重要的是,我建议不要通过尝试暗示方面来对抗布局系统。如您所见,您必须尝试实现一些方法来帮助布局。
I can offer two examples. Neither of them use layouts...
我可以举两个例子。他们都不使用布局......
The first uses a child QLabel
to show the image, and drives its fixed size off of the resize event:
第一个使用子项QLabel
来显示图像,并从 resize 事件驱动其固定大小:
// imagelabel.h
class ImageLabel : public QWidget
{
Q_OBJECT
public:
explicit ImageLabel(QWidget *parent = 0);
const QPixmap* pixmap() const;
public slots:
void setPixmap(const QPixmap&);
protected:
void resizeEvent(QResizeEvent *);
private slots:
void resizeImage();
private:
QLabel *label;
};
// imagelabel.cpp
ImageLabel::ImageLabel(QWidget *parent) :
QWidget(parent)
{
label = new QLabel(this);
label->setScaledContents(true);
label->setFixedSize(0,0);
}
void ImageLabel::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
resizeImage();
}
const QPixmap* ImageLabel::pixmap() const {
return label->pixmap();
}
void ImageLabel::setPixmap (const QPixmap &pixmap){
label->setPixmap(pixmap);
resizeImage();
}
void ImageLabel::resizeImage() {
QSize pixSize = label->pixmap()->size();
pixSize.scale(size(), Qt::KeepAspectRatio);
label->setFixedSize(pixSize);
}
The second example is based off of the answer given by @Arnold_Spence. It is even shorter as it doesn't use a child QLabel. It just draws the pixmap in the paint event:
第二个示例基于@Arnold_Spence 给出的答案。它甚至更短,因为它不使用子 QLabel。它只是在paint事件中绘制像素图:
// imagelabel2.h
class ImageLabel2 : public QWidget
{
Q_OBJECT
public:
explicit ImageLabel2(QWidget *parent = 0);
const QPixmap* pixmap() const;
public slots:
void setPixmap(const QPixmap&);
protected:
void paintEvent(QPaintEvent *);
private:
QPixmap pix;
};
// imagelabel2.cpp
ImageLabel2::ImageLabel2(QWidget *parent) :
QWidget(parent)
{
}
void ImageLabel2::paintEvent(QPaintEvent *event) {
QWidget::paintEvent(event);
if (pix.isNull())
return;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QSize pixSize = pix.size();
pixSize.scale(event->rect().size(), Qt::KeepAspectRatio);
QPixmap scaledPix = pix.scaled(pixSize,
Qt::KeepAspectRatio,
Qt::SmoothTransformation
);
painter.drawPixmap(QPoint(), scaledPix);
}
const QPixmap* ImageLabel2::pixmap() const {
return &pix;
}
void ImageLabel2::setPixmap (const QPixmap &pixmap){
pix = pixmap;
}
回答by Arnold Spence
There is no facility built into QLabel
to maintain the aspect ratio of the image. Since Qlabel
probably has functionality that you don't need, you should subclass QWidget
and override the paintEvent()
to render the image the way you want.
没有内置工具QLabel
来保持图像的纵横比。由于Qlabel
可能具有您不需要的功能,您应该子类化QWidget
并覆盖paintEvent()
以按照您想要的方式渲染图像。