QT 多屏幕截图

该博客介绍了一个使用Qt实现的多显示器截图工具,能够根据鼠标位置在相应屏幕上截图,并提供了截图区域选择、撤销功能。通过QDesktopWidget获取屏幕信息,QImage进行图像处理,同时利用信号槽机制进行事件处理。

目前百度能百度到的,都是让大家调用以下方法获取屏幕

QGuiApplication::primaryScreen();

但这个函数只能获取主屏幕,对多个显示器的截屏就完全不好使了。

所以用以下方法获取所有显示器,并判断当前鼠标、界面位于哪个显示器,即可实现多个屏幕的截图。

int curMonitor = deskTop->screenNumber ( this );
this->baseScreen = screens.at(curMonitor);

截图主要事件为鼠标按下,鼠标移动,鼠标抬起。需要一个全局的点来标记鼠标最开始按下时的点。

以下为三个事件的处理:

void QtScreenShot::mousePressEvent(QMouseEvent* e)
{
    this->startPoint = e->pos();
    this->startGlobalPoint = e->globalPos();
}

void QtScreenShot::mouseMoveEvent(QMouseEvent* e)
{
    QPoint curPoint;
    curPoint = e->pos();
    if (hasArea)
    {
        qDebug() << "return";
        return;
    }
    int posX = startPoint.x();
    int posY = startPoint.y();
    int posWid = curPoint.x() - startPoint.x();
    int posHig = curPoint.y() - startPoint.y();

    this->editArea->setGeometry(posX, posY, posWid, posHig);
    QImage ima = this->getSelectImage(posX, posY, posWid, posHig);
    this->editArea->setBgImage(ima);
    this->editArea->show();
}

void QtScreenShot::mouseReleaseEvent(QMouseEvent* e)
{
    if (e->button() == Qt::RightButton)
    {
        closeAll();
        this->accept();
        return;
    }
    if (hasArea)
    {
        qDebug() << "return";
        return;
    }
    QPoint curPoint;
    curPoint = e->pos();
    int posX = startPoint.x();
    int posY = startPoint.y();
    int posWid = curPoint.x() - startPoint.x();
    int posHig = curPoint.y() - startPoint.y();

    QPoint glcurPoint;
    glcurPoint = e->globalPos();
    this->globalSelectArea.setRect(startGlobalPoint.x(), startGlobalPoint.y(), glcurPoint.x() - startGlobalPoint.x(), glcurPoint.y() - startGlobalPoint.y());
    this->editArea->setGeometry(posX, posY, posWid, posHig);
    QImage ima = this->getSelectImage(posX, posY, posWid, posHig);
    this->editArea->setBgImage(ima);
    this->editArea->show();
    this->toolBar->setPos(curPoint.x(), curPoint.y());
    this->toolBar->show();
    this->hasArea = true;
}

以下为我写的一个demo。测试界面位于哪个屏幕,就可以在哪个屏幕截图,同时还提供操作撤销功能。

如果需要鼠标位于什么屏幕就在哪个屏幕截图,仅需增加一个定时器,在定时器的槽函数中判断当前鼠标的屏幕并重新初始化。(注意根据hasArea判断是否已经取了截图区域)

具体的demo包括DrawingOperationStack(操作栈)、ScreenShotEditArea(截图编辑区)、ScreenShotToolBar(操作栏)三个部分组成。工程我放入了百度网盘中,链接如下:

链接:https://pan.baidu.com/s/1OaHkAlVBiWPx5FU2z3IMrw 
提取码:gogo

具体的代码也贴出来:

测试用的widget(拖进来个按钮和label,按钮用于触发截图,label显示图片):

#include "widget.h"
#include "ui_widget.h"
#include <QDesktopWidget>
#include <QLabel>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->hide();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    QDesktopWidget* deskTop = QApplication::desktop();
    int curMonitor = deskTop->screenNumber(this);
    st = new QtScreenShot(curMonitor,this);
    st->setParent(this);
    connect(st,SIGNAL(onScreenShotOK()),this,SLOT(closeScreenShot()));
    st->exec();
}

void Widget::closeScreenShot()
{
    QImage image = st->getScreenShotImage();
    image = image.scaled(ui->label_1->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    QPixmap im = QPixmap::fromImage(image);
    ui->label_1->setPixmap(im);
    st->accept();
}

drawingoperationstack.h:

#ifndef DRAWINGOPERATIONSTACK_H
#define DRAWINGOPERATIONSTACK_H

#include <QObject>
#include <QRect>
#include <QStack>
struct DrawingOperation{
    int curMode;
    QRect recogRect;
    QRect tempRect;
};

class DrawingOperationStack
{
public:
    DrawingOperationStack();
    void pushInStack(int curMode, QRect rectr, QRect rectt);
    DrawingOperation popStack();
    DrawingOperation getCurOperation();
    bool isEmptyStack();
private:
    QStack<DrawingOperation*> stack;

};

#endif // DRAWINGOPERATIONSTACK_H

drawingoperationstack.cpp

#include "drawingoperationstack.h"
#include <QDebug>
DrawingOperationStack::DrawingOperationStack()
{
    this->stack.clear();
}

void DrawingOperationStack::pushInStack(int curMode, QRect rectr, QRect rectt)
{
    DrawingOperation *st;
    st = new DrawingOperation;
    st->curMode = curMode;
    st->recogRect = rectr;
    st->tempRect = rectt;
    //qDebug()<<st->mode<<st->rect;
    this->stack.push(st);
}

DrawingOperation DrawingOperationStack::popStack()
{
    DrawingOperation op;
    op.curMode = -1;
    op.recogRect = QRect(0,0,0,0);
    op.tempRect = QRect(0,0,0,0);

    if(this->stack.isEmpty())
    {
        return op;
    }
    DrawingOperation *opera = this->stack.pop();
    op.recogRect = opera->recogRect;
    op.tempRect = opera->tempRect;
    op.curMode = opera->curMode;
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值