C++ 如何调整图像的大小以在Qt中缩放?
我创建了一个名为ImageLabel的类,它扩展了QLabel。我希望它保持图像的大小比,无论它是如何伸展显示。当你把窗户调大的时候,它工作的很好。当你试图缩小窗口时,问题就出现了:它不会调整高度,而是让它伸展开来。我该如何解决这个问题C++ 如何调整图像的大小以在Qt中缩放?,c++,qt,C++,Qt,我创建了一个名为ImageLabel的类,它扩展了QLabel。我希望它保持图像的大小比,无论它是如何伸展显示。当你把窗户调大的时候,它工作的很好。当你试图缩小窗口时,问题就出现了:它不会调整高度,而是让它伸展开来。我该如何解决这个问题 int ImageLabel::heightForWidth(int width) const { int height = (this->size.height()*width)/this->size.width(); return heig
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();
}
QLabel
中没有内置用于保持图像纵横比的功能。由于Qlabel
可能具有您不需要的功能,因此您应该对QWidget
进行子类化,并覆盖paintEvent()
,以您想要的方式呈现图像。有几种方法可以做到这一点,但最重要的是,我建议您不要试图通过提示方面来对抗布局系统。如您所见,您必须尝试并实现一些方法来帮助布局
我可以举两个例子。他们都不使用布局
第一个使用子QLabel
显示图像,并将其固定大小从调整大小事件中移出:
//imagelabel.h
类ImageLabel:公共QWidget
{
Q_对象
公众:
显式ImageLabel(QWidget*parent=0);
常量QPixmap*pixmap()常量;
公众时段:
void setPixmap(const QPixmap&);
受保护的:
void resizeEvent(QResizeEvent*);
专用插槽:
void resizeImage();
私人:
QLabel*标签;
};
//imagelabel.cpp
ImageLabel::ImageLabel(QWidget*父项):
QWidget(父级)
{
标签=新的QLabel(本);
标签->设置缩放内容(真);
标签->设置固定大小(0,0);
}
void ImageLabel::resizeEvent(QResizeEvent*事件){
QWidget::resizeEvent(事件);
调整图像大小();
}
常量QPixmap*ImageLabel::pixmap()常量{
返回标签->pixmap();
}
void ImageLabel::setPixmap(常量QPixmap和pixmap){
标签->设置pixmap(pixmap);
调整图像大小();
}
void ImageLabel::resizeImage(){
QSize-pixSize=label->pixmap()->size();
scale(size(),Qt::KeepAspectRatio);
标签->设置固定大小(像素大小);
}
第二个例子基于@Arnold_Spence给出的答案。它甚至更短,因为它不使用子QLabel。它只是在绘制事件中绘制像素贴图:
// 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;
}
是的,这就是为什么我添加了
heightForWidth
功能,这些功能在Qlabel
中是缺乏的。问题不仅仅是绘画,它是关于布局的。您可以让一个小部件尝试向布局提供反馈,告诉它想要的大小,并始终将图像绘制到小部件的完整尺寸,或者您可以允许布局以任何方式调整小部件的大小,并始终在小部件的边界内以适当的比例和位置绘制图像。前者可能会变得复杂,后者似乎更容易。@chacham15:我实际上认为在绘画活动中这样做是一个好建议,因为这样可以让你明确地画出你想要的确切的像素贴图,而不是反对布局。您可以在组合QLabel上设置固定大小,并使用resizeEvent不断调整子对象的大小。方法paintEvent
看起来很简单,我不明白它是如何与布局系统交互的。它如何告诉布局系统仅为高度分配正确的宽度?它看起来没有告诉它任何事情,只是利用了它现有的资源。在这种情况下,您可能会有令人讨厌的页边距,对吗?正如我所说,它不使用布局。您可以将此ImageLabel
放置到一个布局中,该布局将驱动其大小。但是当ImageLabel
对这些大小变化做出反应时,它将控制pixmap的精确显示。是的,如果将父窗口小部件设置得很宽,则可以留有边距。如果你想让它居中,那么为drawPixmap
调用获得一个合适的QPoint
只需要一点数学知识。实际上,这里重要的是你是否需要它来有一些对齐选项。除此之外,您只需将其与其他小部件一起放入布局中。这个小部件应该做的就是保持一个pixmap正确缩放,与小部件中可用空间的某个区域对齐。我想做一个图片拼贴,每张图片紧挨着另一张(想象一下像pinterest一样)。我想知道的是,父布局如何知道要给它多少空间,这样它就不会有疯狂的边距?澄清一下,这两种方法对我都有效,但只有在我(在pyQt中)对实例执行了以下操作之后:imageLabelSizePolicy=QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding);imageLabelSizePolicy.setHeightForWidth(真);imageLabel.setSizePolicy(imageLabelSizePolicy)
。这可能是Qt n00b的评论,但我相信在将来的某个时候,另一个Qt n00b会出现在这个页面上。