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

[SOLVED] Scaled background image using stylesheet

Scheduled Pinned Locked Moved General and Desktop
17 Posts 5 Posters 114.0k 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.
  • C Offline
    C Offline
    clochydd
    wrote on last edited by
    #6

    Hi, if using the styleSheet is not mandatory: There a some good tips to sizing an image with the right aspect ratio in the Qt Image Viewer Example.

    1 Reply Last reply
    0
    • 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