使用Qt实现截图功能
Qt截图有很多方法,这里不做详述,只用到截取整个屏幕的方法:
QScreen *screen = QGuiApplication::primaryScreen();
有时间还可以实现可以提取局部控件的截屏,这在一般的截图工具中都存在
参考链接:https://zhuanlan.zhihu.com/p/212230990
基本上就是使用该作者所写的内容,因为要把截图功能作为OCR软件中的一个模块,所以加了右键选项和一个信号,用于把结果发出来。
细节可以查看参考链接,这里不做详述。
添加应用当前截图功能与信号
//在右键弹出的菜单中添加一个按钮
menu->addAction("应用当前截图", this, SLOT(SelectScreen()));
//定义一个信号,用于发出截屏的图像
signals:
void sig_SelectImg(QImage img);
//设置按钮的槽函数
void ScreenWidget::SelectScreen()
{
int x = screen->getLeftUp().x();
int y = screen->getLeftUp().y();
int w = screen->getRightDown().x() - x;
int h = screen->getRightDown().y() - y;
close();
QPixmap pix = fullScreen->copy(x, y, w, h);
emit sig_SelectImg(pix.toImage());
}
详细代码
screen.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QObject>
#include <QWidget>
#include <QMenu>
#include <QPoint>
#include <QSize>
class Screen
{
public:
enum STATUS {SELECT, MOV, SET_W_H};
Screen() {}
Screen(QSize size);
void setStart(QPoint pos);
void setEnd(QPoint pos);
QPoint getStart();
QPoint getEnd();
QPoint getLeftUp();
QPoint getRightDown();
STATUS getStatus();
void setStatus(STATUS status);
int width();
int height();
bool isInArea(QPoint pos); // 检测pos是否在截图区域内
void move(QPoint p); // 按 p 移动截图区域
private:
QPoint leftUpPos, rightDownPos; //记录 截图区域 左上角、右下角
QPoint startPos, endPos; //记录 鼠标开始位置、结束位置
int maxWidth, maxHeight; //记录屏幕大小
STATUS status; //三个状态: 选择区域、移动区域、设置width height
void cmpPoint(QPoint &s, QPoint &e);//比较两位置,判断左上角、右下角
};
screen.cpp
#pragma once
#pragma execution_character_set("utf-8")
#include "screen.h"
#include <QMutex>
#include <QApplication>
#include <QPainter>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QEvent>
#include <QDateTime>
#include <QStringList>
Screen::Screen(QSize size)
{
maxWidth = size.width();
maxHeight = size.height();
startPos = QPoint(-1, -1);
endPos = startPos;
leftUpPos = startPos;
rightDownPos = startPos;
status = SELECT;
}
int Screen::width()
{
return maxWidth;
}
int Screen::height()
{
return maxHeight;
}
Screen::STATUS Screen::getStatus()
{
return status;
}
void Screen::setStatus(STATUS status)
{
this->status = status;
}
void Screen::setEnd(QPoint pos)
{
endPos = pos;
leftUpPos = startPos;
rightDownPos = endPos;
cmpPoint(leftUpPos, rightDownPos);
}
void Screen::setStart(QPoint pos)
{
startPos = pos;
}
QPoint Screen::getEnd()
{
return endPos;
}
QPoint Screen::getStart()
{
return startPos;
}
QPoint Screen::getLeftUp()
{
return leftUpPos;
}
QPoint Screen::getRightDown()
{
return rightDownPos;
}
bool Screen::isInArea(QPoint pos)
{
if (pos.x() > leftUpPos.x() && pos.x() < rightDownPos.x() && pos.y() > leftUpPos.y() && pos.y() < rightDownPos.y()) {
return true;
}
return false;
}
void Screen::move(QPoint p)
{
int lx = leftUpPos.x() + p.x();
int ly = leftUpPos.y() + p.y();
int rx = rightDownPos.x() + p.x();
int ry = rightDownPos.y() + p.y();
if (lx < 0) {
lx = 0;
rx -= p.x();
}
if (ly < 0) {
ly = 0;
ry -= p.y();
}
if (rx > maxWidth) {
rx = maxWidth;
lx -= p.x();
}
if (ry > maxHeight) {
ry = maxHeight;
ly -= p.y();
}
leftUpPos = QPoint(lx, ly);
rightDownPos = QPoint(rx, ry);
startPos = leftUpPos;
endPos = rightDownPos;
}
void Screen::cmpPoint(QPoint &leftTop, QPoint &rightDown)
{
QPoint l = leftTop;
QPoint r = rightDown;
if (l.x() <= r.x()) {
if (l.y() <= r.y()) {
;
} else {
leftTop.setY(r.y());
rightDown.setY(l.y());
}
} else {
if (l.y() < r.y()) {
leftTop.setX(r.x());
rightDown.setX(l.x());
} else {
QPoint tmp;
tmp = leftTop;
leftTop = rightDown;
rightDown = tmp;
}
}
}
screenwidget.h
#pragma once
#pragma execution_character_set("utf-8")
#include <QWidget>
#include <QWidget>
#include <QMenu>
#include <QPoint>
#include <QSize>
#include "screen.h"
//截屏窗口类
class ScreenWidget : public QWidget
{
Q_OBJECT
public:
static ScreenWidget *Instance();
explicit ScreenWidget(QWidget *parent = 0);
private:
static QScopedPointer<ScreenWidget> self;
QMenu *menu; //右键菜单对象
Screen *screen; //截屏对象
QPixmap *fullScreen; //保存全屏图像
QPixmap *bgScreen; //模糊背景图
QPoint movPos; //坐标
protected:
void contextMenuEvent(QContextMenuEvent *);
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void paintEvent(QPaintEvent *);
void showEvent(QShowEvent *);
signals:
void sig_SelectImg(QImage img);
private slots:
void saveScreen();
void saveFullScreen();
void saveScreenOther();
void saveFullOther();
void SelectScreen();
};
screenwidget.cpp
//#pragma once
#pragma execution_character_set("utf-8")
#include "screenwidget.h"
#include <QMutex>
#include <QApplication>
#include <QPainter>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QEvent>
#include <QDateTime>
#include <QStringList>
#include <QMouseEvent>
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
#include <QScreen>
#endif
#define STRDATETIME qPrintable (QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"))
QScopedPointer<ScreenWidget> ScreenWidget::self;
ScreenWidget *ScreenWidget::Instance()
{
if (self.isNull()) {
static QMutex mutex;
QMutexLocker locker(&mutex);
if (self.isNull()) {
self.reset(new ScreenWidget);
}
}
return self.data();
}
ScreenWidget::ScreenWidget(QWidget *parent) : QWidget(parent)
{
//this->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
menu = new QMenu(this);
menu->addAction("应用当前截图", this, SLOT(SelectScreen()));
menu->addAction("保存当前截图", this, SLOT(saveScreen()));
menu->addAction("保存全屏截图", this, SLOT(saveFullScreen()));
menu->addAction("截图另存为 ", this, SLOT(saveScreenOther()));
menu->addAction("全屏另存为 ", this, SLOT(saveFullOther()));
// menu->addAction("退出截图", this, SLOT(hide()));
menu->addAction("退出截图 ", this, SLOT(close()));
screen = new Screen(QApplication::desktop()->size());
fullScreen = new QPixmap();
}
void ScreenWidget::paintEvent(QPaintEvent *)
{
int x = screen->getLeftUp().x();
int y = screen->getLeftUp().y();
int w = screen->getRightDown().x() - x;
int h = screen->getRightDown().y() - y;
QPainter painter(this);
QPen pen;
pen.setColor(Qt::green);
pen.setWidth(2);
pen.setStyle(Qt::DotLine);
painter.setPen(pen);
painter.drawPixmap(0, 0, *bgScreen);
if (w != 0 && h != 0) {
painter.drawPixmap(x, y, fullScreen->copy(x, y, w, h));
}
painter.drawRect(x, y, w, h);
pen.setColor(Qt::yellow);
painter.setPen(pen);
painter.drawText(x + 2, y - 8, tr("截图范围:( %1 x %2 ) - ( %3 x %4 ) 图片大小:( %5 x %6 )")
.arg(x).arg(y).arg(x + w).arg(y + h).arg(w).arg(h));
}
void ScreenWidget::showEvent(QShowEvent *)
{
QPoint point(-1, -1);
screen->setStart(point);
screen->setEnd(point);
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
*fullScreen = fullScreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height());
#else
QScreen *pscreen = QApplication::primaryScreen();
*fullScreen = pscreen->grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height());
#endif
//设置透明度实现模糊背景
QPixmap pix(screen->width(), screen->height());
pix.fill((QColor(160, 160, 160, 200)));
bgScreen = new QPixmap(*fullScreen);
QPainter p(bgScreen);
p.drawPixmap(0, 0, pix);
}
void ScreenWidget::saveScreen()
{
int x = screen->getLeftUp().x();
int y = screen->getLeftUp().y();
int w = screen->getRightDown().x() - x;
int h = screen->getRightDown().y() - y;
QString fileName = QString("%1/screen_%2.png").arg(qApp->applicationDirPath()).arg(STRDATETIME);
fullScreen->copy(x, y, w, h).save(fileName, "png");
close();
//QPixmap pix = fullScreen->copy(x, y, w, h);
//emit sig_SelectImg(pix.toImage());
}
void ScreenWidget::saveFullScreen()
{
QString fileName = QString("%1/full_%2.png").arg(qApp->applicationDirPath()).arg(STRDATETIME);
fullScreen->save(fileName, "png");
close();
}
void ScreenWidget::saveScreenOther()
{
QString name = QString("%1.png").arg(STRDATETIME);
QString fileName = QFileDialog::getSaveFileName(this, "保存图片", name, "png Files (*.png)");
if (!fileName.endsWith(".png")) {
fileName += ".png";
}
if (fileName.length() > 0) {
int x = screen->getLeftUp().x();
int y = screen->getLeftUp().y();
int w = screen->getRightDown().x() - x;
int h = screen->getRightDown().y() - y;
fullScreen->copy(x, y, w, h).save(fileName, "png");
close();
}
}
void ScreenWidget::saveFullOther()
{
QString name = QString("%1.png").arg(STRDATETIME);
QString fileName = QFileDialog::getSaveFileName(this, "保存图片", name, "png Files (*.png)");
if (!fileName.endsWith(".png")) {
fileName += ".png";
}
if (fileName.length() > 0) {
fullScreen->save(fileName, "png");
close();
}
}
void ScreenWidget::SelectScreen()
{
int x = screen->getLeftUp().x();
int y = screen->getLeftUp().y();
int w = screen->getRightDown().x() - x;
int h = screen->getRightDown().y() - y;
close();
QPixmap pix = fullScreen->copy(x, y, w, h);
emit sig_SelectImg(pix.toImage());
}
void ScreenWidget::mouseMoveEvent(QMouseEvent *e)
{
if (screen->getStatus() == Screen::SELECT) {
screen->setEnd(e->pos());
}
else if (screen->getStatus() == Screen::MOV) {
QPoint p(e->x() - movPos.x(), e->y() - movPos.y());
screen->move(p);
movPos = e->pos();
}
this->update();
}
void ScreenWidget::mousePressEvent(QMouseEvent *e)
{
int status = screen->getStatus();
if (status == Screen::SELECT) {
screen->setStart(e->pos());
}
else if (status == Screen::MOV) {
if (screen->isInArea(e->pos()) == false) {
screen->setStart(e->pos());
screen->setStatus(Screen::SELECT);
}
else {
movPos = e->pos();
this->setCursor(Qt::SizeAllCursor);
}
}
this->update();
}
void ScreenWidget::mouseReleaseEvent(QMouseEvent *)
{
if (screen->getStatus() == Screen::SELECT) {
screen->setStatus(Screen::MOV);
}
else if (screen->getStatus() == Screen::MOV) {
this->setCursor(Qt::ArrowCursor);
}
}
void ScreenWidget::contextMenuEvent(QContextMenuEvent *)
{
this->setCursor(Qt::ArrowCursor);
menu->exec(cursor().pos());
}