I have a QWidget that I don\'t want to show on screen. Instead I want to get a pixmap of the widget every time it is repainted, in order to send it to another part of the ap
I know that this question is old, but I want to add some clarity on the solution, posting some actual working code for future reference.
sourceWidget is the widget that we want to render (aka capture the content as image)
sourceFrame is the parent of sourceWidget
renderLabel is the target in which we want to render the sourceWidget
This is the .h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFrame>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MyEventFilter : public QObject {
Q_OBJECT
public:
MyEventFilter(QObject* parent = nullptr);
protected:
bool eventFilter(QObject* obj, QEvent* event) override;
};
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();
QFrame* sourceFrame;
QWidget* sourceWidget;
QLabel* renderLabel;
private:
Ui::MainWindow* ui;
MyEventFilter* myEventFilter;
};
#endif // MAINWINDOW_H
This is the .cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QDebug>
#include <QPaintEvent>
MyEventFilter::MyEventFilter(QObject *parent) : QObject(parent) {
Q_UNUSED(parent);
}
bool MyEventFilter::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::Paint) {
QPaintEvent* paintEvent = static_cast<QPaintEvent*>(event);
qDebug() << "Paint Event on" << obj << parent();
if (qobject_cast<MainWindow*>(parent())) {
//QImage image = qobject_cast<MainWindow*>(parent())->sourceWidget->grab().toImage();
QPixmap pixmap = qobject_cast<MainWindow*>(parent())->sourceWidget->grab();
qobject_cast<MainWindow*>(parent())->renderLabel->setPixmap(pixmap);
}
Q_UNUSED(paintEvent);
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
sourceFrame = ui->sourceFrame;
sourceWidget = ui->sourceWidget;
renderLabel = ui->renderLabel;
myEventFilter = nullptr;
myEventFilter = new MyEventFilter(this);
sourceFrame->installEventFilter(myEventFilter);
}
MainWindow::~MainWindow() {
delete ui;
}
Well I found a solution. I took all the content of the widget that I wanted to grab, and placed it inside a Frame. Then I grabbed the Frame. It's not really elegant but it works.
As another way - you can do next check:
void paintEvent(QPaintEvent*)
{
QPainter painter(this);
// If painter redirection was turned on, the painter will *not* paint on `this`!
// Painting code
//...
if ( this == qobject_cast< QWidget * >( painter.device() ) )
{
// Do grabbing
}
}
paintEvent is called both for painting on widget and on grabbing. painter->device()
will return not null, but instance of QWidget *
object only when current painting is on widget. In case of drawing on QPixmap
- it will return QPixmap *
. So you need to call grabbing code only when painting is performed only on real widget.