QWidget::render() in custom QWidget
-
Hello everyone,
I made a custom QStackedWidget with the purpose of an animated transition from one widget to another - Slide in and out.
I had issues with moving the QWidgets directly so I decided to make a screenshot of the new and old widget, show those, and move them with a QParallelAnimationGroup.
I did this the following way:
QPoint pNext = widget(slideTo)->pos(); pNow = widget(iCIndex)->pos(); QPixmap pmCurrent = QPixmap(widget(iCIndex)->size()); widget(iCIndex)->render(&pmCurrent); QPixmap pmSlideTo = QPixmap(widget(slideTo)->size()); widget(slideTo)->render(&pmSlideTo); QLabel *lblCurrent = new QLabel(this); QLabel *lblSlideTo = new QLabel(this); lblCurrent->resize(widget(iCIndex)->size()); lblSlideTo->resize(widget(slideTo)->size()); lblCurrent->show(); lblSlideTo->show(); lblCurrent->setPixmap(pmCurrent); lblSlideTo->setPixmap(pmSlideTo); lblCurrent->raise(); lblSlideTo->raise(); lblCurrent->move(0,0); lblSlideTo->move(pNext.x() - iOffsetX, pNext.y()-iOffsetY); QPropertyAnimation *anCurrent = new QPropertyAnimation(lblCurrent,"pos"); QPropertyAnimation *anSlideto = new QPropertyAnimation(lblSlideTo,"pos"); QParallelAnimationGroup *anGroup = new QParallelAnimationGroup; .... .... connect(anGroup, &QParallelAnimationGroup::finished, lblCurrent, &QLabel::deleteLater); connect(anGroup, &QParallelAnimationGroup::finished, lblSlideTo, &QLabel::deleteLater); connect(anGroup, &QParallelAnimationGroup::finished, [=]{ setCurrentIndex(iNext); widget(iNow)->hide(); widget(iNow)->move(pNow); bActive = false; emit AnimationFinished(); }); anGroup->start();
The problem is,
QWidget::render()
completely ignores the stylesheet of the cStackedWidget. I applied it withui->cStackedMain->setStyleSheet("cStackedWidget{background-color:white;}");
from the GUI-Class. The white background does not show in the QDesigner, but it is correctly painted when I start the program.
If I set a global StyleSheet like
centralWidget->setStyleSheet{background-color:white;}
then render() accepts the white background. However I don't want to/can't use that , because it would overwrite the children of the whole ui.
From the docu I know, that I have the overwrite the paintEvent in my custom widget class, which I did:
void cStackedWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); }
So, I'm kinda lost and out of ideas, if anyone could help me, I would be very grateful.
If needed/asked for, I'll look in uploading the class so it can be tested easily!?
-
Hi
I think the issue is just who is parent ?
The stylesheet will affect children so if it works with the custom widget when
centralWidget->setStyleSheet{background-color:white;}
has the style so to speak
then it sounds like your custom is just owned by something not affected and hence its children will no either.I use only a single stylesheet on mainwindow. Not pr control as i think it becomes uncontrollable very fast.
Maybe i misunderstand your issue and what works and what do not work.
Your paint looks correct :) -
To add to @mrjj
@J.Hilk said in QWidget::render() in custom QWidget:
However I don't want to/can't use that , because it would overwrite the children of the whole ui.
You can use object name specific stylesheet see id selector in http://doc.qt.io/qt-5/stylesheet-syntax.html#selector-types
I had issues with moving the QWidgets directly
I implemented something similar here SelettoreImmagini.h SelettoreImmagini.cpp it's from one of the very first programs I wrote in Qt (a snake game) so it's VERY far from good (and the variable names are in italian) but gives you an idea, basically you keep 1 widget always visible then, you add the widgets that you want to scroll as its children but you never add them to a layout but instead manually resize them to the parent widget, at this point you are free to animate the "pos" property of the child widgets. In the linked example I move 2 QLabels
-
Hi, sorry for the delay, was a crazy weekend on my side. Thanks for the fast replies
I think I'll have to be more precise with my description.
First off, you may find a small example project here.
So, let's say I set a single StyleSheet on the QMainWindow, like this:
this->setStyleSheet("QMainWindow{background-color:white;}\ cStackedWidget{background-color:red;}\ QLabel{background-color:blue;}");
I get a exactly what I want, white background/Mainwindow, red Stackedwidget and blue labels.
As soon as I use render() on the first QWidget of the QStackedWidget. the red is completly ignored, I get the default light grey for the stacked widget and blue QLabelsWhen I set the StyleSheet like this:
this->setStyleSheet("background-color:red;");
Everything is Red but, render() actually captures the QStackedWidget color correctly.
LineBreakAs I'm writing this, I actually find the crux of the problem.
this:
this->setStyleSheet("QMainWindow{background-color:white;}\ cStackedWidget{background-color:red;}\ QLabel{background-color:blue;}");
Paints the ui, like I whoud expect it to but its apparently not doing the job thoroughly enough.
Each "page" of the QStackedWidget is a QWidget, and using the above code paints the QWidgets red as well but not for the QWidget::render() function.Using this StyleSheet:
this->setStyleSheet("QMainWindow{background-color:white;}\ cStackedWidget{background-color:red;}\ QWidget{background-color:red;}\ QLabel{background-color:blue;}");
I see no difference for when the widget is painted, but now QWidget::render actually accepts the red background.
So, is this a bug ot intended behaviour?
-
@J.Hilk
Super with a sample. +5
I see what you mean.
Its a bit odd. So first it accepts the stylesheet but when
you render an image for slide animation it is
not applied. I thought it would be exactly the
same in and render() would just call paint.Interesting :)
-
Just realized, that I had still thread still open.
I'll share how I managed to circumvent the problem. Sadly I haven't found a
real
solution as of now.In the function that makes the screenshot, I added this line just before calling
QWidget::render
this->setStyleSheet("cStackedWidget {background-color:white;}" "QWidget#LiveStatus{background-color:white;}" ... //List of all QStackedwidget Pages ... "QWidget#FanThreshhold{background-color:white;}");
For some reason I have to set the stylesheet new for each time. Simply setting this once will not work.
Anyway, I'll mark it as solved,
unless someone else has a new idea !?