Search code examples
c++qtqpainter

An auto-scaled on-off background image in a QLineEdit


I have a couple of QLineEdit widgets that need to have their backgrounds appear and disappear upon certain code changes, and need those backgrounds to also rescale when widget size changes.

I am getting quite lost in all the stackoverflow and documentation on the Qt website. My main point of confusion is how I register only specific widgets with a paintEvent function I make.

In pseudo-ish code, I've been led to believe that my auto-scaling background image idea requires some combination of QPainter and QPixmap:

void MyGUI::paintEvent(QWidget mywidget, string path){
  QPainter painter(mywidget);

  QPixmap _mypix(path);

  int widgetHeight = mywidget.height();
  int imageHeight = _mypix.height();
  float imageratio = _mypix.width()/_mypix.height();
  if(imageHeight > widgetHeight){
    painter.drawPixmap(0,0,imageratio*widgetHeight, widgetHeight, _mypix);
  }
  else{ painter.drawPixmap(0,0,_mypix.width(), _mypix.height(), _mypix);}
}

Then in the main UI, I want to call the above function situationally to turn on and off this background image. While the image is on, though, I want it to resize as per the above function (aka depending on its widget's height, not the main GUI height):

Blah blah constructor stuff
{
  ui->setupUi(this);
  
  paintEvent(ui->widget1, "path\to\background1.png");
  paintEvent(ui->widget2, "path\to\background2.png");
  
  connect(this,SIGNAL(MaybeTurnOffBackground()),this,SLOT(TurnOffBackgroundSometimes(bool)));
}

void MyGUI::TurnOffBackgroundSometimes(bool backgroundOn)
{
  if(backgroundOn)
  {
    paintEvent(ui->widget1, "path\to\background1.png");
    paintEvent(ui->widget2, "path\to\background2.png");
  }
  else{
    //something that removes the images
  }
}

Hope it's clear enough. I have no idea how to make this type of behavior come about. I get the sense I am somewhat overcomplicating things by using the paintEvent business, but I'm not sure what the alternative is.


Solution

  • Solved my own problem. Ended up doing it entirely in stylesheets. I don't know what my philosophical opposition was to using image instead of background-image, aside from the worry that it would interact poorly with text that is inputted into the QLineEdit. Thankfully that is not a concern, and text receives the most Z height in the box overall so the image will still appear behind it.

    Some answers have specified that you need a border, e.g. "border: 1px solid white". I tested first with border, then without, and it functions the same so I left the border out. YMMV.

    #myWidget1{
        image: url(":/main/assets/myAsset1.png");
        image-position: left;
        padding: 5px;
    }
    

    Regarding the on-off feature... I'd actually already solved this. I just created a custom property, and toggled it off and on in SLOTS as necessary.

    Stylesheet:

    #myWidget1{
        background:rgba(125,0,0,55);
    }
    
    #myWidget1[status="active"]{
        image: url(":/main/assets/myAsset1.png");
        image-position: left;
        padding: 5px;
    }
    

    Sample code in a slot:

    if(active){
      ui->myWidget1->setProperty("status","active");
    }
    else{
      ui->myWidget1->setProperty("status","notactive");
    }
    

    The nice thing is I don't actually have to define what style "notactive" takes in the stylesheet. It just defaults to the baseline style.