Qt学习笔记: 实现截图效果

首先在这里感谢刘大师,提供的源码进行学习。如有冒犯之意,请联系我将其删除,谢谢!这是刘大师的个人主页.

目前跟随刘大师的脚步,学习了一下采用Qt实现截图的效果,具体效果如下:


这里写图片描述

废话不多说,先谈谈这个功能。
首先我们了解一下这个截图:首先,我们是点击“截图工具“,然后弹出灰色的背景,在拖动鼠标进行截图,最后在保存图片。

截屏思想:点击截屏工具的时候,截取全屏的像素,并且将全屏保存到一个全局的变量pixmap中。然后,在点击鼠标移动,截取一个相应的矩形。将其绘制出来。然后在保存。。
那么接下来就可以贴上源码进行解释了:

void frmAPI::on_btnScreenAPI_clicked()
{
    frmScreen::Instance()->showFullScreen();//显示全屏widget
}

这个是点击截图工具以后实现的槽函数。showFllScreen() –> 将widget全屏显示(于是就有了点击以后全屏变灰色)。接着便是调用frmScreen的回调函数

frmScreen::frmScreen(QWidget *parent) : QDialog(parent)
{
    this->initForm();
}
//初始化框架
void frmScreen::initForm()
{
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);//隐藏标题栏,窗体出现在最顶层

    menu = new QMenu(this);
    menu->addAction("保存截图", this, SLOT(saveScreen()));
    menu->addAction("截图另存为", this, SLOT(saveScreenOther()));
    menu->addAction("全屏截图", this, SLOT(saveFullScreen()));
    menu->addAction("退出截图", this, SLOT(hide()));

    //取得屏幕大小
    qDebug()<<QApplication::desktop()->size();
    screen = new ScreenAPI(QApplication::desktop()->size());
    //保存全屏图像
    fullScreen = new QPixmap();
}

初始化这里先创建了一个对象ScreenAPI。这个对象便是实现屏幕API的一个类。该类定义如下:这是一个纯C++定义的一个类。(没有Q_OBJECT

class ScreenAPI
{
public:
    enum STATUS {SELECT, MOV, SET_W_H};
    ScreenAPI() {}
    ScreenAPI(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);//比较两位置,判断左上角、右下角
};

具体构造函数如下。

ScreenAPI::ScreenAPI(QSize size)
{
    maxWidth = size.width();//获得整个屏幕的大小
    maxHeight = size.height();

    startPos = QPoint(-1, -1);//开始坐标
    endPos = startPos;//结束坐标
    leftUpPos = startPos;//左上角坐标
    rightDownPos = startPos;//右下角坐标
    status = SELECT;
}

由于在.h文件中重写了 void showEvent(QShowEvent )事件,因此在显示窗体的时候,会被调用。并且重写了void paintEvent(QPaintEvent );事件重绘函数,因此也会被调用一次。

//显示窗口Widget发出事件被调用
void frmScreen::showEvent(QShowEvent *)
{
    QPoint point(-1, -1);
    screen->setStart(point);//设置开启坐标点
    screen->setEnd(point);//设置结束坐标点

    //全屏图像,抓取窗体
    *fullScreen = QPixmap::grabWindow(QApplication::desktop()->winId(), 0, 0, screen->width(), screen->height());

    //设置透明度实现模糊背景
    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);
}
//重绘事件  update调用
void frmScreen::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);

    QFont font;
    font.setFamily("Microsoft YaHei");
    font.setPointSize(10);
    painter.setFont(font);

    //截屏思想:点击截屏工具的时候,截取全屏的像素,并且将全屏保存到一个全局的变量pixmap中。
    //然后,在点击鼠标移动,截取一个相应的矩形。将其绘制出来。
    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 frmScreen::mousePressEvent(QMouseEvent *e)
{
    int status = screen->getStatus();//获取状态

    if (status == ScreenAPI::SELECT) {
        screen->setStart(e->pos());
    } else if (status == ScreenAPI::MOV) {
        if (screen->isInArea(e->pos()) == false) {
            screen->setStart(e->pos());
            screen->setStatus(ScreenAPI::SELECT);
        } else {
            movPos = e->pos();
            this->setCursor(Qt::SizeAllCursor);
        }
    }

    update();
}
//鼠标移动事件
void frmScreen::mouseMoveEvent(QMouseEvent *e)
{
    if (screen->getStatus() == ScreenAPI::SELECT) {//选择区域
        screen->setEnd(e->pos());//得到结束点坐标
    } else if (screen->getStatus() == ScreenAPI::MOV) {//移动区域
        QPoint p(e->x() - movPos.x(), e->y() - movPos.y());
        screen->move(p);
        movPos = e->pos();
    }

    update();
}
//鼠标释放事件
void frmScreen::mouseReleaseEvent(QMouseEvent *)
{
    if (screen->getStatus() == ScreenAPI::SELECT) {
        screen->setStatus(ScreenAPI::MOV);
    } else if (screen->getStatus() == ScreenAPI::MOV) {
        this->setCursor(Qt::ArrowCursor);
    }
}

到此,就实现了这个功能。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值