Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Containing picture window resizing stops every few pixels
Qt 6.11 is out! See what's new in the release blog

Containing picture window resizing stops every few pixels

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 1.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • puzzled_giraffeP Offline
    puzzled_giraffeP Offline
    puzzled_giraffe
    wrote on last edited by puzzled_giraffe
    #1

    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:
    alt text
    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.
    alt text
    How to fix this and make window resing normal?

    how did I get here?

    kshegunovK 1 Reply Last reply
    0
    • puzzled_giraffeP puzzled_giraffe

      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:
      alt text
      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.
      alt text
      How to fix this and make window resing normal?

      kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by
      #2

      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:

      1. Save the original picture in your class (as you'd done).
      2. Override the paintEvent method and paint the image as scaled there. Don't do rescaling in the resizeEvent, you're killing the responsiveness that way.

      Read and abide by the Qt Code of Conduct

      puzzled_giraffeP 1 Reply Last reply
      3
      • kshegunovK kshegunov

        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:

        1. Save the original picture in your class (as you'd done).
        2. Override the paintEvent method and paint the image as scaled there. Don't do rescaling in the resizeEvent, you're killing the responsiveness that way.
        puzzled_giraffeP Offline
        puzzled_giraffeP Offline
        puzzled_giraffe
        wrote on last edited by puzzled_giraffe
        #3

        @kshegunov Thanks for your advice.

        So, look like I found an answer. If someone needs it:
        header

        class 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:
        it works

        how did I get here?

        1 Reply Last reply
        3

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved