利用QWidget的render函数实现拷贝当前窗体内容

需求提出:

    有时,我们需要对当前窗体内容进行拷贝。如:

  •  用户要求每隔几秒就要知道当前窗体屏幕都有些啥,让程序每隔几秒将当前屏幕快照,发送到他们程序进行显示。
  • 程序需要记录当前屏幕内容,每隔一段时间以图片的形式,将当前窗体的内容保存起来,以作为日志记录。

实现如下:

.h文件

#pragma once

#include 
#include "ui_QtWidgetsApplication1.h"
#include
#include  
class QtWidgetsApplication1 : public QMainWindow
{
    Q_OBJECT

public:
    QtWidgetsApplication1(QWidget *parent = nullptr);
    ~QtWidgetsApplication1();

protected:
    void paintEvent(QPaintEvent* event);

    void copyWnd();

private:
    Ui::QtWidgetsApplication1Class ui;
    QTimer* m_pTimer{nullptr};              // 保存当前窗口内容到图片的定时器
    QTimer* m_pChangeColorTimer{ nullptr }; // 改变颜色的定时器
    QRandomGenerator m_rndColorGenerator;   // 产生颜色的随机器
    int m_nRed{255};                        // 颜色的红色分量值
    int m_nGreen{ 0 };                      // 颜色的绿色分量值
    int m_nBlue{ 0 };                       // 颜色的蓝色分量值
};

.cpp文件

#include "QtWidgetsApplication1.h"
#include
#include
#include
#include
#include
#include
QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    
    m_pTimer = new QTimer(this);
    m_pTimer->setInterval(3000);
    connect(m_pTimer, &QTimer::timeout, this, [=] {copyWnd(); });

    m_pChangeColorTimer = new QTimer(this);
    m_pChangeColorTimer->setInterval(1000);

    auto seedTime = QDateTime::currentDateTime().currentMSecsSinceEpoch();
    m_rndColorGenerator.seed(seedTime);

    connect(m_pChangeColorTimer, &QTimer::timeout, this, [=] {
        m_nRed = m_rndColorGenerator.bounded(0, 256);
        m_nGreen = m_rndColorGenerator.bounded(0, 256);
        m_nBlue = m_rndColorGenerator.bounded(0, 256);
        qInfo() << m_nRed << "  " << m_nGreen << "  " << m_nBlue << "  ";
        update();
        });

    m_pChangeColorTimer->start();

    auto pCopyWndMenu = new QMenu(QString::fromLocal8Bit("窗体拷贝"), this);
    auto pStartCopyWndAction = new QAction(QString::fromLocal8Bit("开始拷贝"), this);
    connect(pStartCopyWndAction, &QAction::triggered, this, [=] {m_pTimer->start(); });
    pCopyWndMenu->addAction(pStartCopyWndAction);
    this->menuBar()->addMenu(pCopyWndMenu);

  
}

QtWidgetsApplication1::~QtWidgetsApplication1()
{}

void QtWidgetsApplication1::paintEvent(QPaintEvent* event)
{
    QPainter p(this);
    p.setBrush(QBrush(QColor(m_nRed, m_nGreen, m_nBlue)));
    p.drawEllipse(this->centralWidget()->rect().adjusted(20, 40, 20, 30));
}

void QtWidgetsApplication1::copyWnd()
{
    qreal dpr = window()->windowHandle()->devicePixelRatio();
    QPixmap pixmap(this->size() * dpr);
    pixmap.setDevicePixelRatio(dpr);
    this->render(&pixmap);

    auto qsCurrentTime = QDateTime::currentDateTime().toString();
    auto qsFileName = QString::fromLocal8Bit("%1.png").arg(qsCurrentTime);
    qsFileName.replace(":", "-"); // :是非法文件名,:不能构成文件名,用-替代
    auto b = pixmap.save(qsFileName, "PNG");
}

定时器每次都会将当前窗体拷贝并存为png图片放在当前目录下。如下是结果:

利用QWidget的render函数实现拷贝当前窗体内容_第1张图片

说明:

          在实际项目中,可以开启一个线程,进行轮替删除,即只保留离现在最近的某几张图片,将 时间久远的图片删除,否则图片占用硬盘会越来越大。 

         QWidget的render函数定义如下:

void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), QWidget::RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren))

用法及参数说明:

target:这个参数是指将QWidget对象的内容绘制、渲染到哪里,本例是渲染即绘制到QPixmap对象上,即图片上。

targetOffset:这个参数是指渲染到目标上时,从目标的何处绘制、渲染,如从图片左边框50像素、上边框50像素的地方绘制,如下:

 this->render(&pixmap, QPoint(50, 50));

结果如下:

利用QWidget的render函数实现拷贝当前窗体内容_第2张图片

sourceRegion:表示源被渲染到目标区域,本例中的源是指整个窗体。如果不设置,则默认是当前整个窗体,你可以设置窗体的某部分区域。

renderFlags:渲染标识,决定渲染动作如何进行。其值为以下三个枚举:

QWidget::DrawWindowBackground

如果该标识被启用,即使

autoFillBackground未被设置,

源窗体的背景也会被渲染到目标中去。该标识默认是启用的。

QWidget::DrawChildren

如果该标识被启用,该窗体下的所有子窗体会被递归地渲染到目标中去,该标识默认是启用的。

QWidget::IgnoreMask

如果该标识被启用,该窗体的

QWidget::mask()不会被渲染到目标,默认该标识是禁用的

注意:

  • 在调用render之前,确保在目标上调用了QPainter::end()。如下:
 QPainter painter(this);
  ...
  painter.end();  // 先必须保证调用了目标的QPainter对象的end函数
  myWidget->render(this);
  • 如果需要对QOpenGLWidget对象实现同样的功能,请用QOpenGLWidget::grabFramebuffer()方法替代,而不要用本方法,本方法只使用一般QWidget对象。

上述copyWnd()中的devicePixelRatio函数的用法及理解,请参考:

《QWindow类devicePixelRatio函数作用》博文。 

上述copyWnd()中window()返回本窗体的QWindow对象,而window()->windowHandle()则返回QWindow对象的native widget对象。关于QWidget的parentWidget、window、nativeParent窗体的概念及用法,请参考:《QWidget的parentWidget、window、nativeParentWidget区别与理解》。

你可能感兴趣的:(QT,拷贝当前窗体内容,render函数)