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. [SOLVED] Scaled background image using stylesheet
QtWS25 Last Chance

[SOLVED] Scaled background image using stylesheet

Scheduled Pinned Locked Moved General and Desktop
17 Posts 5 Posters 113.8k Views
  • 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.
  • Chris KawaC Offline
    Chris KawaC Offline
    Chris Kawa
    Lifetime Qt Champion
    wrote on last edited by
    #7

    Yeah, you won't get the exactly same effect with border-image, but you can change one of the dimensions from stretch to repeat.
    This would keep the aspect ratio. If that's no good I would just override paintEvent and draw it however you need with QPainter.

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mbnoimi
      wrote on last edited by Chris Kawa
      #8

      @chrisaverage said:

      If that's no good I would just override paintEvent and draw it however you need with QPainter.

      Unfortunately I couldn't find a solution using qss so may you please guide from where I can start by using paintEvent.

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mbnoimi
        wrote on last edited by Chris Kawa
        #9

        I fixed this issue by using the following:

        void MainWindow::paintEvent(QPaintEvent *pe)
        {
            QPixmap pixmap;
            pixmap.load(":/res/background.jpg");
            QPainter paint(this);
            int widWidth = this->ui->centralWidget->width();
            int widHeight = this->ui->centralWidget->height();
            pixmap = pixmap.scaled(widWidth, widHeight, Qt::KeepAspectRatioByExpanding);
            paint.drawPixmap(0, 0, pixmap);
            QWidget::paintEvent(pe);
        }
        

        P.S. I feel very upset because I hoped to use QSS, I always prefer to use it instead of manual theme manipulation .

        1 Reply Last reply
        0
        • Chris KawaC Offline
          Chris KawaC Offline
          Chris Kawa
          Lifetime Qt Champion
          wrote on last edited by Chris Kawa
          #10

          A comment on your paintEvent(). At the end you call QWidget::paintEvent(). This is not a good idea. If someday you flip the autoFillBackground flag or a future theme adds some background to the widgets, it will paint over whatever you draw.
          Either call it before you draw or, if you're filling the whole area anyway, don't call it at all.
          Also you can just do QPixmap pixmap(":/res/background.jpg"), no need to load separately. You could also store it somewhere and not load again each time it's drawn.

          As for you being upset - cheer up :) QSS just doesn't support it so there's nothing you can do about it. Unless of course you want to implement it and offer a patch to Qt ;)
          And it's not like it's slower or anything. It just looks funny.
          If you don't want to mix this drawing code into your widget there's another way.
          Make a class that derives from QObject and implement eventFilter method that will do the drawing for the paint event. Then you can install instance of that class on your widget. Something ike this:

          SuperBackgroundPainter blah(":/res/background.jpg");
          MainWindow w;
          w.installEventFilter(blah);
          w.show();
          ...
          

          This way you can nicely separate this unfortunate painting stuff from the main purpose of your widget.

          1 Reply Last reply
          1
          • M Offline
            M Offline
            mbnoimi
            wrote on last edited by Chris Kawa
            #11

            @chrisaverage said:

            A comment on your paintEvent(). At the end you call QWidget::paintEvent(). This is not a good idea. If someday you flip the autoFillBackground flag or a future theme adds some background to the widgets, it will paint over whatever you draw.
            Either call it before you draw or, if you're filling the whole area anyway, don't call it at all.
            Also you can just do QPixmap pixmap(":/res/background.jpg"), no need to load separately. You could also store it somewhere and not load again each time it's drawn.

            I appreciate your comment Chris; Thank you :)

            Below the solution depending on your advice:

            MainWindow::MainWindow(QWidget *parent) :
                QMainWindow(parent),
                ui(new Ui::MainWindow)
            {
                ui->setupUi(this);
                _pixmapBg.load(":/res/background.jpg");
            }
            
            void MainWindow::paintEvent(QPaintEvent *pe)
            {
                QPainter paint(this);
                int widWidth = this->ui->centralWidget->width();
                int widHeight = this->ui->centralWidget->height();
                _pixmapBg = _pixmapBg.scaled(widWidth, widHeight, Qt::KeepAspectRatioByExpanding);
                paint.drawPixmap(0, 0, _pixmapBg);
            }
            

            A Side discussion:
            The solution above scales the pixmap from (0,0) do you've any idea how to scale the pixmap from the center of the pixmap?

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mbnoimi
              wrote on last edited by Chris Kawa
              #12

              @mbnoimi said:

              A Side discussion:
              The solution above scales the pixmap from (0,0) do you've any idea how to scale the pixmap from the center of the pixmap?

              Forget it guys, I found out the solution as following:

              void MainWindow::paintEvent(QPaintEvent *pe)
              {
                  QPainter paint(this);
                  int widWidth = this->ui->centralWidget->width();
                  int widHeight = this->ui->centralWidget->height();
                  _pixmapBg = _pixmapBg.scaled(widWidth, widHeight, Qt::KeepAspectRatioByExpanding);
                  QPoint centerOfWidget = ui->centralWidget->rect().center();
                  QRect rectOfPixmap = _pixmapBg.rect();
                  rectOfPixmap.moveCenter(centerOfWidget);
                  paint.drawPixmap(rectOfPixmap.topLeft(), _pixmapBg);
              }
              
              1 Reply Last reply
              0
              • Chris KawaC Offline
                Chris KawaC Offline
                Chris Kawa
                Lifetime Qt Champion
                wrote on last edited by Chris Kawa
                #13

                Yeah, another thing I noticed now is that you're using scaled(). That's also creating a copy of the image, thus is not very good performance-wise. It's better to just use one of the drawPixmap methods with explicit dimensions.
                Besides the way you use scaled() is no good. If your image is 1000x1000 and you scale it to 10x10 and then back to say 500x500 it will be ugly blurred.

                Calculating dimensions might be a little harder, but is a lot faster than copying bitmaps around.

                This is one way to do the drawing (sorry if it's not perfect, It's kinda brain-fart :) )

                QPainter painter(this);
                
                auto winSize = size();
                auto pixmapRatio = (float)_pixmapBg.width() / _pixmapBg.height();
                auto windowRatio = (float)winSize.width() / winSize.height();
                
                if(pixmapRatio > windowRatio)
                {
                  auto newWidth = (int)(winSize.height() * pixmapRatio);
                  auto offset = (newWidth - winSize.width()) / -2;
                  painter.drawPixmap(offset, 0, newWidth, winSize.height(), _pixmapBg);
                }
                else
                {
                  auto newHeight = (int)(winSize.width() / pixmapRatio);
                  painter.drawPixmap(0, 0, winSize.width(), newHeight, _pixmapBg);
                }
                
                1 Reply Last reply
                1
                • M Offline
                  M Offline
                  mbnoimi
                  wrote on last edited by
                  #14

                  Thank you but it doesn't show it in the cente.

                  Any way loading _pixmapBg inside paintEvent() will fix scaled() issue.

                  1 Reply Last reply
                  0
                  • Chris KawaC Offline
                    Chris KawaC Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by Chris Kawa
                    #15

                    Didn't noticed it should also center vertically. Easy fix:

                    else
                    {
                      auto newHeight = (int)(winSize.width() / pixmapRatio);
                      auto offset = (newHeight - winSize.height()) / -2;
                      painter.drawPixmap(0, offset, winSize.width(), newHeight, _pixmapBg);
                    }
                    

                    As said before loading it and then scaling inside paint event is not a good idea. It's IO and then also copying. You're doing a lot of the same work over and over again.

                    1 Reply Last reply
                    1
                    • SGaistS SGaist

                      Hi,

                      AFAIK, background-size is not supported by Qt's style-sheet

                      Maybe image might do the trick ?

                      Hope it helps

                      said_osloS Offline
                      said_osloS Offline
                      said_oslo
                      wrote on last edited by
                      #16

                      @SGaist
                      Screenshot 2021-07-05 at 14.43.26.png
                      Hi.
                      I have a problem to move to top my rfid interface.
                      It's seems like my interface hidden by a logo or something else.
                      please if you have some solutions. please shares it ?

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #17

                        Hi,

                        Not knowing anything about the code you are using, I cannot answer.

                        Since you necro-posted this thread, did any of the advices put here help ? Do they relate to your issue ?

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0

                        • Login

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