前言
本文主要讲述了在Windows平台下使用Qt实现类似微信截图的功能,通过下面示例进行讲解,以便大家学习,如有错误之处,欢迎大家批评指正。
项目效果
提示:以下是本篇文章正文内容,下面案例可供参考
一、实现思路
1. 创建遮罩层
需要创建一个自定义的QWidget作为遮罩层,这个遮罩层应该覆盖整个屏幕,并且设置为半透明,我创建了ScreenOverlay类,详见下文示例完整代码;
2. 监听截屏按钮点击事件
点击截图按钮后显示遮罩层,并准备进行屏幕截取,在这里调用ScreenOverlay类对象的show()触发ScreenOverlay类中的showEvent()获取全屏截图;
3. 截取屏幕内容
在遮罩层显示后,监听ScreenOverlay类的鼠标事件来定义截图的区域,在鼠标移动过程中使用update()刷新paintEvent(),更新截图显示以及图像信息;
4. 显示截图
鼠标左键松开后获取相应的截图,通过信号与槽发送信号将截图显示在主界面上的QLabel,并隐藏遮罩层。
二、实现截图时隐藏当前窗口
在这里我创建了一个单选按钮,在进行截图时根据单选按钮的状态决定是否隐藏当前窗口,在测试过程中发现当前窗口使用hide()隐藏是有耗时的,所以使用了Qtimer的singleShot函数进行了延时:
//开始截图
void MainWindow::on_pb_screen_clicked()
{
if(ui->rb_hide->isChecked())
{
//当前窗口隐藏有耗时,需要延时触发遮罩类对象的showEvent事件
this->hide();
QTimer::singleShot(200,Qt::PreciseTimer,this,[this]()
{
m_screenOverlay->show();
});
}
else
{
m_screenOverlay->show();
}
}
三、示例完整代码
1.screenoverlay.h
#ifndef SCREENOVERLAY_H
#define SCREENOVERLAY_H
#include <QWidget>
#include <QRect>
#include <QPixmap>
#include <QScreen>
#include <QPainter>
#include <QMouseEvent>
#include <QApplication>
#include <QDesktopWidget>
class ScreenOverlay : public QWidget
{
Q_OBJECT
public:
explicit ScreenOverlay(QWidget *parent = nullptr);
protected:
void showEvent(QShowEvent *) override;
void paintEvent(QPaintEvent *) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
signals:
void signal_shotPixmap(QPixmap shotPixmap);
private:
bool m_selestFlag; //截屏标志
QPoint m_startPoint; //截屏起点
QPoint m_endPoint; //截屏终点
QRect m_selectRect; //截屏矩形区域
QPixmap m_fullScreen; //全屏图像
QPixmap m_blurScreen; //模糊全屏图像
};
#endif // SCREENOVERLAY_H
2.screenoverlay.cpp
#include "screenoverlay.h"
ScreenOverlay::ScreenOverlay(QWidget *parent)
: QWidget(parent, Qt::Window | Qt::FramelessWindowHint)
{
//设置窗口尺寸
this->resize(QApplication::desktop()->size());
m_selestFlag = false;
m_startPoint = QPoint();
m_endPoint = QPoint();
m_selectRect = QRect();
m_fullScreen = QPixmap();
m_blurScreen = QPixmap();
}
//通过show()显式调用
void ScreenOverlay::showEvent(QShowEvent *)
{
//设置透明度实现模糊背景
m_startPoint = QPoint();
m_endPoint = QPoint();
m_selectRect = QRect();
m_fullScreen = QApplication::primaryScreen()->grabWindow(0);
QPixmap pix(m_fullScreen.width(),m_fullScreen.height());
pix.fill((QColor(160, 160, 160, 200)));
m_blurScreen = m_fullScreen;
QPainter p(&m_blurScreen);
p.drawPixmap(0,0,pix);
}
//重写绘图事件
void ScreenOverlay::paintEvent(QPaintEvent *)
{
//创建QPainter对象进行绘制
QPainter painter(this);
QPen pen;
pen.setColor(Qt::green);
pen.setWidth(2);
pen.setStyle(Qt::DotLine);
painter.setPen(pen);
//绘制模糊全屏图像
painter.drawPixmap(0,0,m_blurScreen);
//绘制截屏区域图像
QRect curRect = QRect(m_startPoint,m_endPoint).normalized();
QPoint startPoint = curRect.topLeft();
QPoint endPoint = curRect.bottomRight();
m_selectRect = QRect(startPoint,endPoint);
int x = m_selectRect.x();
int y = m_selectRect.y();
int w = m_selectRect.width();
int h = m_selectRect.height();
painter.drawRect(m_selectRect);
if(!m_selectRect.isEmpty())
{
painter.drawPixmap(x,y,m_fullScreen.copy(m_selectRect));
}
//使用黄色画笔绘制图像信息
painter.setPen(QPen(Qt::yellow));
painter.drawText(x+2,y-8,QString("Pos:(%1 x %2) Size:(%3 x %4)")
.arg(x).arg(y).arg(w).arg(h));
}
//鼠标按下
void ScreenOverlay::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
m_selestFlag = true;
m_startPoint = event->pos();
}
}
//鼠标移动
void ScreenOverlay::mouseMoveEvent(QMouseEvent *event)
{
if(m_selestFlag)
{
m_endPoint = event->pos();
this->update();
}
}
//鼠标松开
void ScreenOverlay::mouseReleaseEvent(QMouseEvent *event)
{
//左键松开获取截图
if(event->button() == Qt::LeftButton)
{
if(m_selestFlag)
{
m_selestFlag = false;
if(!m_selectRect.isEmpty())
{
//从屏幕图像中复制选择区域
QPixmap shotPixmap = m_fullScreen.copy(m_selectRect);
emit signal_shotPixmap(shotPixmap);
//隐藏遮罩层
this->hide();
}
}
}
//右键松开取消
if(event->button() == Qt::RightButton)
{
QPixmap nullPix;
emit signal_shotPixmap(nullPix);
this->hide();
}
}
3.mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include "screenoverlay.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void initWidget();
private slots:
void slot_shotPixmap(QPixmap shotPixmap);
void on_pb_screen_clicked();
private:
Ui::MainWindow *ui;
ScreenOverlay *m_screenOverlay; //屏幕遮罩类对象
};
#endif // MAINWINDOW_H
4.mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->initWidget();
}
MainWindow::~MainWindow()
{
delete ui;
}
//初始化界面
void MainWindow::initWidget()
{
this->setFixedSize(800,600);
//屏幕遮罩类对象
m_screenOverlay = new ScreenOverlay();
connect(m_screenOverlay, &ScreenOverlay::signal_shotPixmap,this,&MainWindow::slot_shotPixmap);
}
//将截图显示在界面上
void MainWindow::slot_shotPixmap(QPixmap shotPixmap)
{
ui->lb_show->clear();
if(!shotPixmap.isNull())
{
ui->lb_show->setPixmap(shotPixmap.scaled(ui->lb_show->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation));
}
this->show();
}
//开始截图
void MainWindow::on_pb_screen_clicked()
{
if(ui->rb_hide->isChecked())
{
//当前窗口隐藏有耗时,需要延时触发遮罩类对象的showEvent事件
this->hide();
QTimer::singleShot(200,Qt::PreciseTimer,this,[this]()
{
m_screenOverlay->show();
});
}
else
{
m_screenOverlay->show();
}
}
5.mainwindow.ui
总结
根据上文的思路我们也是使用Qt实现了截图功能,最主要的其实就是对Qt下事件的使用,这个示例中的遮罩类的鼠标、绘图等事件都进行了重写,如果我们以后遇到类似开发功能,就可以直接使用这个遮罩类,不用再重复造轮子啦~
hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。
参考博客:使用Qt实现截图功能