Render QWidget in QPixmap with system background - c++

When I render a QWidget with a QOpenGLWidget child with transparency objects, I observe a solarization effect when I tried to take a screenshot like the following picture:
The problem comes with the system background because when I remove it, the problem disappear:
.
My question is: What is the solutions to render a QWidget on a QPixmap with the system background?
Here my render code:
QWidget widget;
QPixmap pixmap(widget.size());
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
widget.render(&painter, QPoint(), QRegion(), QWidget::DrawWindowBackground /* the problem is this render flag */ | QWidget::IgnoreMask | QWidget::DrawChildren);
pixmap.save("screenshot.png");
The property setAutoFillBackground(true); and the method grab(); do the same like the first screenshot.
EDIT: There is no OpenGL problem. When I mix two pixmaps (the first with the background and the second with widget children), the solarization problem is still present.

A solution is to set a QPalette with Window role to black in my QOpenGLWidget.
QPalette currentWidgetPalette{ palette() };
currentWidgetPalette.setColor(QPalette::Window, Qt::black);
setPalette(currentWidgetPalette);
EDIT: I found a solution to paint destination in tansparent and source with my widget to compose the pixmap correctly.
painter.setCompositionMode(QPainter::CompositionMode_Destination);
painter.fillRect(result.rect(), Qt::transparent);
painter.setCompositionMode(QPainter::CompositionMode_Source);
widget.render(&painter, QPoint(), QRegion(), QWidget::DrawWindowBackground | QWidget::IgnoreMask | QWidget::DrawChildren);

Related

How to add picture containing transparency to the window background using code?

How to set a png file containing transparency to the window background
using only code and not css/stylesheet?
With the following code the picture is added however, the background became black in the parts where
the image is not painted
ui.setupUi(this);
QPixmap bkgnd(":/pic");
//bkgnd = bkgnd.scaled(this->size(), Qt::IgnoreAspectRatio);
//bkgnd.fill(Qt::transparent);
QPalette palette;
//palette.setColor(QPalette::Window, Qt::transparent);
palette.setBrush(QPalette::Window, bkgnd);
this->setPalette(palette);
//this->setAttribute(Qt::WA_TranslucentBackground, true);
Commented are things i already tried.

Change border color of QWidget using animation

I have tried to change border color of Qwidget for two days but Doesn't work.
so I refered to another code which is posted on the stackoverflow about moving widget. it worked perpectly but I can't change border color using QPropertyAnimation. give some tips for this problem.
QPropertyAnimation *animation = new QPropertyAnimation(ui.defectView, "border-color");
animation->setDuration(2000);
animation->setStartValue(QColor(0, 0, 0));
animation->setEndValue(QColor(240, 240, 240));
animation->start();
There is no QWidget property called "border-color". All it's properties are shown in QWidget documentation. But you can change this color using QSS and animate it. Also consider custom paintEvent depending on your needs.

QT: picture as window

I want to make window frame using some picture. Window shouldn't have borders, titlebars, etc. It also should be hidden from active windows list (in taskbar).
Second part of question I did with:
this->setAttribute(Qt::WA_NoSystemBackground);
this->setAttribute(Qt::WA_QuitOnClose);
this->setAutoFillBackground(true);
this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
for new class which inherits QMainWindow. It's hidden, for example, at gnome taskbar, but in Awn (awant windows navigator) I seed it in the list of active windows :(.
What about first part. I did this some time ago with QRegion, QPixmap and mask in overloaded paintEvent. I've lost the code. Can you help me with this?
regarding the first part of the question, you, probably, looking for smth like this:
void MainWindow::paintEvent(QPaintEvent * event)
{
QPainter painter(this);
QPixmap pixmap = QPixmap();
pixmap.load("/home/my_image.jpg");
painter.drawPixmap(event->rect(), pixmap);
}
as an alternative you can create a label and show it on your main window, smth like this:
QLabel* label = new QLabel(this); // where 'this' is your window
label->setGeometry(this->geometry());
QPixmap pixmap = QPixmap();
pixmap.load("/home/my_image.jpg");
label->setPixmap(pixmap.scaled(label->size(), Qt::KeepAspectRatio));
hope this helps, regards

painting inside widget in Qt

I created a very simple GUI that has a push button and a "Graphics View" widget from Display Widgets. On pushing the button I want a line to be drawn across the "Graphics View" widget. I have changed the name of the "Graphics View" widget to gv by right-clicking the widget in design view and then selecting change objectName. I am not able to understand how should the line be drawn. I read various texts on Qt that provided information about QPainter, PaintEvent etc. But I got more confused.
Kindly help me with this. A small sample code shall be really helpful for me as I am new to Qt.
A QGraphicsView is meant for displaying instances of QGraphicsItem that are managed by a component called QGraphicsScene. In your case, you'd create a QGraphicsLineItem and add it to the scene, or directly create it as an item of the scene by calling the addLine member function of your QGraphicsScene instance.
All drawing will be done by Qt itself, assuming that you did connect your graphics view and scene properly. Be sure to read The Graphics View Framework, which gives you an overview over how these components work.
You will find code examples of how to manage and display a scene using the graphics view framework here: http://doc.trolltech.com/4.6/examples-graphicsview.html
You can paint into a QPainter
Either override the paintevent and draw there
void MyDisplayWidget::paintEvent(QPaintEvent*)
{
QPainter p(this);
p.setPen(Qt::green);
p.drawText(10,10,"hello");
}
Or draw into a QImage and display that
QImage image = QImage(size);
QPainter p(&image);
p.drawText(10,10,"hello");
// draw or save QImage
You can even use the same draw function taking a QPainter * to draw either direct to the screen or to an image.
first you must knew some information about QPainter to have benefit of it.
QPainter provides highly optimized functions to do most of the drawing GUI programs require. It can draw everything from simple graphical primitives (represented by the QPoint, QLine, QRect, QRegion and QPolygon classes) to complex shapes like vector paths .and we use it to draw on paint devices
then render it to view,and we have alot of qpaint devices like : QWidget, QImage, QPixmap, QPicture, QPrinter, and QOpenGLPaintDevice you can use any one of them depending on your requirements then create QGraphic scene and add you paint device as qgraphic scene item to be shown in qgraphic view.
here is simple code:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
scene=new QGraphicsScene(this); //allocate your scene to your main widget
view=new QGraphicsView(scene,this);//here is your view
pixmap=new QPixmap(QSize(700,700));// paint device
view->resize(700,700);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *e)
{
painter=new QPainter;// create your painter
painter->begin(pixmap);//add painter to your paint device
painter->fillRect(0,0,300,300,Qt::red);//draw rect
painter->setPen(Qt::yellow);
painter->drawLine(0,0,700,700);//draw line
painter->end();
scene->addPixmap(*pixmap);// add your paint device to your scene
view->show();//then show your view
}

QGLWidget + QGraphicsScene + QGraphicsView problem

I would like to create a simple thumbnail viewer using QGLWidget, QGraphicsScene and QGraphicsView. And I have a problem with placing QGLWidget on QGraphicsScene. The code is similar to this:
QGraphicsScene *testScene = new QGraphicsScene (0, 0, 400, 400, 0);
QGLWidget *testWidget1 = new QGLWidget();
testWidget1->renderText("Test text1");
QGLWidget *testWidget2 = new QGLWidget();
testWidget2->renderText("Test text2");
testScene->addWidget(testWidget1);
testScene->addWidget(testWidget2);
QGraphicsView *testView = new QGraphicsView();
testView->setScene(testScene);
testView->show()
It is possible to place few QGLWidgets on QGraphicsScene/QGraphicsView? Where I doing something wrong? Is there any other component on which I could embed QGLWidgets and show them on the screen?
Thanks for help
To make QGLWidget show in QGraphicsView, you should redirect painting for it. You can overwrite the paintGL like this:
virtual void MyGLWidget::paintGL()
{
QGLWidget::paintGL();
//support redirecting painting
QPaintDevice* device = QPainter::redirected(this);
if (device != NULL && device != this)
{
QImage image = grabFrameBuffer();
QPainter painter(this);
painter.drawImage(QPointF(0.0,0.0),image);
}
}
It works well for most platforms, but still happens to show black widget.
The QGraphicsScene::addWidget documentation states that QGLWidget is not a supported widget type.
Parenting a QGLWidget onto the viewport of the QGraphicsView doesn't seem to work either.
Edit:
Actually parenting a QGLWidget to the viewport does work provided I put the renderText call within the paintGL method of my test GL widget.
From the QGraphicsView docs:
To render using OpenGL, simply call setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport widget.
So, in order to draw text on the view, use a QGraphicsTextItem rather than trying to draw text using the QGLWidget.