Containing picture window resizing stops every few pixels
-
I have a simple dialog window with horizontal layout and QLable in it. QLable contains image. I use resize event to scale this image to fit window size.
I used code from QT example. Header:
#ifndef SCALEIMGDIALOG_H #define SCALEIMGDIALOG_H #include <QDialog> #include <QLabel> namespace Ui { class ScaleImgDialog; } class ScaleImgDialog : public QDialog { Q_OBJECT public: explicit ScaleImgDialog(QWidget *parent = 0); ~ScaleImgDialog(); protected: void resizeEvent(QResizeEvent *event) override; private: Ui::ScaleImgDialog *ui; QPixmap testImg; }; #endif
and source file:
#include <QDebug> #include "scaleImgDialog.h" #include "ui_scaleImgDialog.h" // main dialog window name is ScaleImgDialog ui_scaleImgDialog.h is generated automatically ScaleImgDialog::ScaleImgDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ScaleImgDialog), testImg(":/images/testImg.jpeg") { ui->setupUi(this); setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint); } ScaleImgDialog::~ScaleImgDialog() { delete ui; } void ScaleImgDialog::resizeEvent(QResizeEvent *) { int newHeight = height(); newHeight -= newHeight / 10; // to prevent recursive resizing // Image heigh is much bigger then width so i use scaling by it ui->imgDisplayLabel->setPixmap(testImg.scaledToHeight(newHeight)); }
Size increase works well. But I faced next problem: when I try to make window smaller it doesn't work properly. Window shrinks a little and resizing stops. On next try it shrinks a little more and stops again and so on:
And second strange thing: if you don't release mouse button it is possible to resize window freely while it is bigger than size on beginning. Maximize window button and return to previous size also works well.
How to fix this and make window resing normal? -
You're doing it wrong. Changing the image is rather expensive, and you can get a lot of resize events. What you should do instead is:
- Save the original picture in your class (as you'd done).
- Override the
paintEvent
method and paint the image as scaled there. Don't do rescaling in theresizeEvent
, you're killing the responsiveness that way.
-
@kshegunov Thanks for your advice.
So, look like I found an answer. If someone needs it:
headerclass ScaleImgDialog : public QDialog { Q_OBJECT public: explicit ScaleImgDialog(QWidget *parent = 0); ~ScaleImgDialog(); protected: void paintEvent(QPaintEvent *) override; void resizeEvent(QResizeEvent *) override; private: Ui::ScaleImgDialog *ui; QPixmap testImg; int imageWidth; int imageHeight; int widthOffset; int heightOffset; };
source:
ScaleImgDialog::ScaleImgDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ScaleImgDialog), testImg(":/images/testImg.jpeg") { ui->setupUi(this); setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint); setWindowFlags(windowFlags() | Qt::WindowMaximizeButtonHint); resizeEvent(nullptr); } ScaleImgDialog::~ScaleImgDialog() { delete ui; } void ScaleImgDialog::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawPixmap(widthOffset, heightOffset, imageWidth, imageHeight, testImg); } void ScaleImgDialog::resizeEvent(QResizeEvent *) { QSize winSize = size(); imageHeight = testImg.height(); imageWidth = testImg.width(); if (imageHeight > winSize.height()) { double heightRatio = (double)winSize.height() / testImg.height(); imageHeight = (int)(testImg.height() * heightRatio); imageWidth = (int)(testImg.width() * heightRatio); } if (imageWidth > winSize.width()) { double widthRatio = (double)winSize.width() / imageWidth; imageHeight = (int)(imageHeight * widthRatio); imageWidth = (int)(imageWidth * widthRatio); } widthOffset = winSize.width() > imageWidth ? ((winSize.width() - imageWidth) / 2) : 0; heightOffset = winSize.height() > imageHeight ? ((winSize.height() - imageHeight) / 2) : 0; }
So all size calculations are done in resizeEvent() (only when they needed) and drawing itself is happening in paintEvent(). This code keeps image size ratio and adds some "white spaces" to borders if necessary: