• Qt 截屏的方法


    最近一个Qt(C++)的项目需要用到截屏的功能,就花时间研究了一下如何实现。
    Qt 确实是好用,截屏只需要下面三行代码就够了。
    1 QDesktopWidget *desk = QApplication::desktop();
    2 QScreen * screen = QGuiApplication::primaryScreen();
    3 QPixmap p = screen->grabWindow(desk->winId());

    这三行代码第一行是获取桌面的窗体对象。
    第二行是获得一个 QScreen 对象。
    第三行是截取屏幕上窗体对象所在区域的图像。

    截取的结果是个QPixmap ,如果需要进一步处理的话,可以转化为 QIamge,一行代码就可以了。

    QImage image = p.toImage();

    原理就这么简单,但是我将这个代码封装了一下,将截屏功能封装成了一个 Camera。一次截屏操作就相当于相机拍一张照片。这样的好处是我这里有大量的相机图像处理的代码模块。将截屏封装成相机之后,就可以非常便捷的连接我的既有代码了。这种方法在设计模式中成为“适配器模式”。

    下面是代码:

      1 #ifndef SCREENCAMERA_H
      2 #define SCREENCAMERA_H
      3 
      4 #include <QThread>
      5 #include <QObject>
      6 #include <QScreen>
      7 #include <QTimer>
      8 
      9 class ScreenCamera;
     10 
     11 /**
     12  * @brief The ScreenCameraInfo class 查询屏幕相机的信息的类
     13  * 用这个类可以查到当前计算机接了几个显示器,给出每个显示器的名称(deviceName)
     14  */
     15 class ScreenCameraInfo
     16 {
     17     friend class ScreenCamera;
     18 public:
     19     explicit ScreenCameraInfo(QScreen * screen = nullptr);
     20     ScreenCameraInfo(const ScreenCameraInfo &info);
     21     /**
     22      * @brief description 没有实现,返回空字符串
     23      * @return 返回空字符串。
     24      */
     25     QString description() const;
     26     /**
     27      * @brief deviceName 给出屏幕的名称,比如 "\\\\.\\DISPLAY1", "VGA1" 一类的名称。
     28      * @return
     29      */
     30     QString deviceName() const;
     31     bool isNull() const;
     32     bool operator!=(const ScreenCameraInfo &other) const;
     33     ScreenCameraInfo &operator=(const ScreenCameraInfo &other);
     34     bool operator==(const ScreenCameraInfo &other) const;
     35 
     36     static QList<ScreenCameraInfo> availableCameras();
     37     static ScreenCameraInfo defaultCamera();
     38 
     39 private:
     40     QScreen* m_screen;
     41 };
     42 
     43 /**
     44  * @brief The ScreenCamera class 将截屏功能封装成一个相机,可以像相机一样的操作。
     45  */
     46 class ScreenCamera : public QThread
     47 {
     48     Q_OBJECT
     49 public:
     50     explicit ScreenCamera(QObject *parent = 0);
     51     explicit ScreenCamera(ScreenCameraInfo &info, QObject *parent = 0);
     52     /**
     53      * @brief openDevice 打开一个特定的截屏相机,当计算机连接了多个显示器时通过这个 info 指定截取某一个屏幕的图像
     54      * @param info
     55      * @return
     56      */
     57     bool openDevice(const ScreenCameraInfo &info);
     58     /**
     59      * @brief setFrameRate 设置定时截屏的帧率。这里模仿相机的帧率设置。
     60      * @param fps  frame per second 每秒的截屏数量。 [0.001 - 50]
     61      */
     62     void setFrameRate(double fps);
     63     /**
     64      * @brief setRoi 设置感兴趣的区域,利用这个函数我们可以只截取屏幕的一部分区域
     65      * @param x 截屏区域的起始X坐标
     66      * @param y 截屏区域的起始Y坐标
     67      * @param width 截屏区域的宽度,-1 表示完整的屏幕宽度
     68      * @param height 截屏区域的高度,-1 表示完整的屏幕高度
     69      */
     70     void setRoi(int x, int y, int width, int height);
     71     void run() override;
     72     /**
     73      * @brief capture 获取截屏图像
     74      * @return
     75      */
     76     QImage capture();
     77 signals:
     78     /**
     79      * @brief imageChanged 定时截取图像时没截取一帧图像就激发一次这个信号
     80      * @param image
     81      */
     82     void imageChanged(const  QImage& image);
     83 public slots:
     84     /**
     85      * @brief start 开始图像采集
     86      */
     87     void start();
     88     /**
     89      * @brief stop 停止图像采集
     90      */
     91     void stop();
     92 
     93 private:
     94     int m_sleepInterval;
     95     QScreen* m_screen;
     96     int m_x;
     97     int m_y;
     98     int m_width;
     99     int m_height;
    100 };
    101 
    102 #endif // SCREENCAMERA_H
      1 #include "ScreenCamera.h"
      2 #include <QApplication>
      3 #include <QDesktopWidget>
      4 #include <QDebug>
      5 
      6 ScreenCameraInfo::ScreenCameraInfo(const ScreenCameraInfo &info)
      7     :m_screen(nullptr)
      8 {
      9     m_screen = info.m_screen;
     10 }
     11 
     12 ScreenCameraInfo::ScreenCameraInfo(QScreen * screen)
     13     :m_screen(nullptr)
     14 {
     15     m_screen = screen;
     16 }
     17 
     18 bool ScreenCameraInfo::isNull() const
     19 {
     20     return (m_screen == nullptr);
     21 }
     22 
     23 QString ScreenCameraInfo::description() const
     24 {
     25     return "";
     26 }
     27 QString ScreenCameraInfo::deviceName() const
     28 {
     29     if(m_screen == nullptr) return "";
     30     return m_screen->name();
     31 }
     32 
     33 ScreenCameraInfo ScreenCameraInfo::defaultCamera()
     34 {
     35     QScreen * w = QGuiApplication::primaryScreen();
     36     return ScreenCameraInfo(w);
     37 }
     38 
     39 QList<ScreenCameraInfo> ScreenCameraInfo::availableCameras()
     40 {
     41     QList<QScreen *> list = QGuiApplication::screens();
     42     QList<ScreenCameraInfo> info;
     43     foreach (QScreen * s, list)
     44     {
     45         ScreenCameraInfo i(s);
     46         info.append(i);
     47     }
     48 
     49     return info;
     50 }
     51 
     52 bool ScreenCameraInfo::operator!=(const ScreenCameraInfo &other) const
     53 {
     54     return (m_screen != other.m_screen);
     55 }
     56 
     57 ScreenCameraInfo & ScreenCameraInfo::operator=(const ScreenCameraInfo &other)
     58 {
     59     m_screen = other.m_screen;
     60     return *this;
     61 }
     62 
     63 bool ScreenCameraInfo::operator==(const ScreenCameraInfo &other) const
     64 {
     65     return m_screen == other.m_screen;
     66 }
     67 
     68 
     69 ScreenCamera::ScreenCamera(ScreenCameraInfo &info, QObject *parent) : QThread(parent)
     70 {
     71     m_screen = info.m_screen;
     72     m_sleepInterval = 500;
     73     m_x = 0;
     74     m_y = 0;
     75     m_width = -1;
     76     m_height = -1;
     77 }
     78 
     79 ScreenCamera::ScreenCamera(QObject *parent) : QThread(parent)
     80 {
     81     m_screen = nullptr;
     82     m_sleepInterval = 500;
     83     m_x = 0;
     84     m_y = 0;
     85     m_width = -1;
     86     m_height = -1;
     87 }
     88 
     89 bool ScreenCamera::openDevice(const ScreenCameraInfo &info)
     90 {
     91     m_screen = info.m_screen;
     92     return (m_screen);
     93 }
     94 
     95 void ScreenCamera::setFrameRate(double fps)
     96 {
     97     fps = qBound(0.001, fps, 50.0);
     98     m_sleepInterval = 1000 / fps;  
     99 }
    100 
    101 void ScreenCamera::setRoi(int x, int y, int width, int height)
    102 {
    103     if(m_screen)
    104     {
    105         QRect rect = m_screen->geometry();
    106 
    107         m_x = qBound(0, x, rect.width());
    108         m_y = qBound(0, y, rect.height());
    109         m_width = qBound(-1, width, rect.width());
    110         m_height = qBound(-1, height, rect.height());
    111     }
    112 }
    113 
    114 void ScreenCamera::run()
    115 {
    116     while(1)
    117     {
    118         if(m_screen)
    119         {
    120             QDesktopWidget *desk = QApplication::desktop();
    121             //qDebug() << "m_width = " << m_width;
    122             //qDebug() << "m_height = " << m_height;
    123             QPixmap p = m_screen->grabWindow(desk->winId(), m_x, m_y, m_width, m_height);
    124             QImage image = p.toImage();
    125             emit imageChanged(image);
    126         }
    127         msleep(m_sleepInterval);
    128     }
    129 }
    130 
    131 QImage ScreenCamera::capture()
    132 {
    133     if(m_screen)
    134     {
    135         QDesktopWidget *desk = QApplication::desktop();
    136         QPixmap p = m_screen->grabWindow(desk->winId(), m_x, m_y, m_width, m_height);
    137         QImage image = p.toImage();
    138         return image;
    139     }
    140     return QImage();
    141 }
    142 
    143 void ScreenCamera::stop()
    144 {
    145     terminate();
    146 }
    147 
    148 void ScreenCamera::start()
    149 {
    150     QThread::start(QThread::InheritPriority);
    151 }

    用法很简答,下面给个代码片段:

    1 ScreenCameraInfo info = ScreenCameraInfo::defaultCamera();
    2 qDebug() << info.deviceName();
    3 m_screenCamera = new ScreenCamera(info);
    4 connect(m_screenCamera, SIGNAL(imageChanged(QImage)), m_cameraImage, SLOT(setImage(QImage)));
    5 m_screenCamera->setRoi(0, 0, 500, 500);
    6 m_screenCamera->start();
  • 相关阅读:
    编程之美:位运算应用集萃
    【总结系列】互联网服务端技术体系:高性能之缓存面面观
    【总结系列】互联网服务端技术体系:高性能之并发(Java)
    【总结系列】互联网服务端技术体系:高性能之数据库索引
    【总结系列】互联网服务端技术体系:可扩展之数据分区
    一道关于二叉树的字节面试题的思考
    python基础之range()函数和random模块
    记录下第一次参加leetcode 周赛
    几种方法实现“反转字符串”
    c# 自动更新程序
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/16520034.html
Copyright © 2020-2023  润新知