4

我有一个不想在屏幕上显示的 QWidget。相反,我想在每次重新绘制时获取小部件的像素图,以便将其发送到我正在处理的应用程序的另一部分。API 提供了两种方法:QPixmap::grabWidgetQWidget::render

问题是这两种方法都会触发一个新paintEvent的小部件,创建一个小部件的递归重绘,所以它们不应该在paintEvent方法内部使用。

那么,每次重新绘制小部件时,我怎么能得到一个代表小部件的像素图呢?

4

3 回答 3

5

作为另一种方式 - 您可以进行下一次检查:

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。仅当当前绘画在小部件上时painter->device()才会返回非空,而是对象的实例。QWidget *在绘图的情况下QPixmap- 它会返回QPixmap *。因此,仅当仅在真实小部件上执行绘画时才需要调用抓取代码。

于 2013-10-08T11:34:25.883 回答
0

好吧,我找到了解决方案。我获取了我想要抓取的小部件的所有内容,并将其放置在 Frame 中。然后我抓住了框架。它不是很优雅,但它确实有效。

于 2013-10-08T09:32:49.057 回答
0

我知道这个问题很老,但我想在解决方案上添加一些清晰度,发布一些实际的工作代码以供将来参考。

sourceWidget是我们要渲染的小部件(也就是将内容捕获为图像)

sourceFrame是 sourceWidget 的父级

renderLabel是我们要在其中渲染 sourceWidget 的目标

这是.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

这是.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;
}
于 2020-12-28T10:51:55.510 回答