2

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.

S. B.
  • 63
  • 4
  • QWidget::paintEvent is a virtual method that you can override and modify it accordingly. You should never call paintEvent on a specific widget. If you want to trigger it, you should call the widget's update() method, which will trigger a paint event. – santahopar Jan 20 '22 at 21:15
  • Upload your code to GitHub,.I can take a look at it. – santahopar Jan 20 '22 at 21:16
  • How do I make sure the background only gets applied to a specific widget then? Should I not use paintEvents? Using paintEvent is not a requirement here, it's just what I thought was required to be able to do some math on the image before I set it as the QLineEdit background. – S. B. Jan 20 '22 at 21:21
  • I took a look at your code and it needs lots of changes. You pass around widgets as values instead of pointers, that's something that you should never do. I'd suggest you take a step back and start with some tutorials on Qt. – santahopar Jan 21 '22 at 16:29
  • Here's a link: https://www.youtube.com/watch?v=6KtOzh0StTc&list=PL2D1942A4688E9D63 – santahopar Jan 21 '22 at 16:30
  • I threw this code together in 2 minutes for the sake of the stackoverflow. Admittedly it's been a while since I've touched Qt, but I'm editing a different application and wanted to approximate it close enough since you requested to see some code. I would love to get back to the question at hand – S. B. Jan 22 '22 at 17:21
  • Do you have prior experience with C++ and C++ UI frameworks? Because from the code it seemed like you didn't, regardless whether it was done in 2 minutes, or 1:) I'm just doing my best to help you, that's all. Which is why I gave you the link to some Qt tutorials, which will help you to hit the ground up and running. – santahopar Jan 23 '22 at 17:10

1 Answers1

1

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.

S. B.
  • 63
  • 4