How to grab a qwidget /render it in a pixmap everytime it needs to be repainted?

前端 未结 3 1190
我在风中等你
我在风中等你 2021-01-06 03:27

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

相关标签:
3条回答
  • 2021-01-06 03:50

    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;
    }
    
    0 讨论(0)
  • 2021-01-06 03:51

    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.

    0 讨论(0)
  • 2021-01-06 04:13

    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.

    0 讨论(0)
提交回复
热议问题