最近一个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。一次截屏操作就相当于相机拍一张照片。这样的好处是我这里有大量的相机图像处理的代码模块。将截屏封装成相机之后,就可以非常便捷的连接我的既有代码了。这种方法在设计模式中成为“适配器模式”。
下面是代码:
本文福利,
莬
费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击
莬
费领取↓↓
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();
本文福利,
莬
费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击
莬
费领取↓↓