我有一个不想在屏幕上显示的 QWidget。相反,我想在每次重新绘制时获取小部件的像素图,以便将其发送到我正在处理的应用程序的另一部分。API 提供了两种方法:QPixmap::grabWidget和QWidget::render
问题是这两种方法都会触发一个新paintEvent
的小部件,创建一个小部件的递归重绘,所以它们不应该在paintEvent
方法内部使用。
那么,每次重新绘制小部件时,我怎么能得到一个代表小部件的像素图呢?
我有一个不想在屏幕上显示的 QWidget。相反,我想在每次重新绘制时获取小部件的像素图,以便将其发送到我正在处理的应用程序的另一部分。API 提供了两种方法:QPixmap::grabWidget和QWidget::render
问题是这两种方法都会触发一个新paintEvent
的小部件,创建一个小部件的递归重绘,所以它们不应该在paintEvent
方法内部使用。
那么,每次重新绘制小部件时,我怎么能得到一个代表小部件的像素图呢?
作为另一种方式 - 您可以进行下一次检查:
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 *
。因此,仅当仅在真实小部件上执行绘画时才需要调用抓取代码。
好吧,我找到了解决方案。我获取了我想要抓取的小部件的所有内容,并将其放置在 Frame 中。然后我抓住了框架。它不是很优雅,但它确实有效。
我知道这个问题很老,但我想在解决方案上添加一些清晰度,发布一些实际的工作代码以供将来参考。
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;
}