├── HTYScreenPen
├── HTYScreenPen.pro
├── README.md
├── icons
├── brush.png
├── color.svg
├── ellipse.svg
├── icon.png
├── image.svg
├── line.svg
├── quit.svg
├── rect.svg
└── trash.svg
├── install.sh
├── main.cpp
├── mainwindow.cpp
├── mainwindow.h
├── mainwindow.ui
└── res.qrc
/HTYScreenPen:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonichy/HTYScreenPen/6a71a794184ddaa5cdc4c389881cdd7610c8c1b8/HTYScreenPen
--------------------------------------------------------------------------------
/HTYScreenPen.pro:
--------------------------------------------------------------------------------
1 | QT += core gui
2 |
3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
4 |
5 | TARGET = HTYScreenPen
6 | TEMPLATE = app
7 |
8 | SOURCES += \
9 | main.cpp \
10 | mainwindow.cpp
11 |
12 | HEADERS += \
13 | mainwindow.h
14 |
15 | FORMS += \
16 | mainwindow.ui
17 |
18 | RESOURCES += \
19 | res.qrc
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 海天鹰屏幕笔
2 | 基于 Qt 的微型屏幕涂鸦程序,利用透明窗体实现涂鸦层。
3 | 已编译好的 HTYScreenPen 程序适用 64 位 Linux 系统 Qt5 环境。
4 | install.sh 自动生成desktop文件。
5 | 配合系统快捷键启动更方便。
6 | ### 1.2 (2019-05-12)
7 | 实现:带颜色的画刷鼠标指针。
8 | 修复:不先用画刷其他工具不能绘图的问题。
9 | ### 1.1 (2019-04-04)
10 | 动态鼠标指针,可以指示颜色和线粗。
11 | ### 1.0 (2018-11-08)
12 | 铅笔、直线、长方形、椭圆、图片、颜色工具。
--------------------------------------------------------------------------------
/icons/brush.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonichy/HTYScreenPen/6a71a794184ddaa5cdc4c389881cdd7610c8c1b8/icons/brush.png
--------------------------------------------------------------------------------
/icons/color.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/icons/ellipse.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sonichy/HTYScreenPen/6a71a794184ddaa5cdc4c389881cdd7610c8c1b8/icons/icon.png
--------------------------------------------------------------------------------
/icons/image.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/icons/line.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/icons/quit.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/icons/rect.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/icons/trash.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | s="[Desktop Entry]\nName=海天鹰涂鸦\nComment=简单的屏幕涂鸦程序\nExec=`pwd`/HTYScreenPen\nIcon=`pwd`/icons/icon.png\nPath=`pwd`\nTerminal=false\nType=Application\nCategories=Graphics;"
2 | echo -e $s > HTYScreenPen.desktop
3 | cp `pwd`/HTYScreenPen.desktop ~/.local/share/applications/HTYScreenPen.desktop
4 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | qSetMessagePattern("[ %{file}: %{line} ] %{message}");
8 | MainWindow w;
9 | w.show();
10 | return a.exec();
11 | }
--------------------------------------------------------------------------------
/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "math.h"
2 | #include "mainwindow.h"
3 | #include "ui_mainwindow.h"
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | MainWindow::MainWindow(QWidget *parent) :
13 | QMainWindow(parent),
14 | ui(new Ui::MainWindow)
15 | {
16 | ui->setupUi(this);
17 | setWindowIcon(QIcon(":/icons/icon.png"));
18 | setWindowFlags(Qt::FramelessWindowHint);
19 | setAttribute(Qt::WA_TranslucentBackground, true);
20 | showMaximized();
21 | ui->pushButton_menu->setCursor(Qt::PointingHandCursor);
22 | ui->pushButton_menu->move(QApplication::desktop()->width() - ui->pushButton_menu->width() - 20, QApplication::desktop()->height() - 2.5 * ui->pushButton_menu->height());
23 |
24 | clear();
25 | pen.setColor(Qt::red);
26 | pen.setWidth(5);
27 | pen.setCapStyle(Qt::RoundCap);
28 | pen.setJoinStyle(Qt::RoundJoin);
29 | brush = QBrush(Qt::transparent, Qt::SolidPattern);
30 | //brush.setColor(Qt::red);
31 | setBrush();
32 |
33 | QMenu *menu = new QMenu;
34 | menu->setStyleSheet("color:rgb(255,255,255); background:rgba(0,0,0,100);");
35 | menu->setAttribute(Qt::WA_TranslucentBackground, true);
36 | menu->setAutoFillBackground(true);
37 | QAction *action_brush = new QAction(QIcon(":/icons/brush.png"), "画笔", this);
38 | action_brush->setShortcut(QKeySequence(Qt::Key_1));
39 | QAction *action_line = new QAction(QIcon(":/icons/line.svg"), "直线", this);
40 | action_line->setShortcut(QKeySequence(Qt::Key_2));
41 | QAction *action_ellipse = new QAction(QIcon(":/icons/ellipse.svg"), "椭圆", this);
42 | action_ellipse->setShortcut(QKeySequence(Qt::Key_3));
43 | QAction *action_rect = new QAction(QIcon(":/icons/rect.svg"), "方框", this);
44 | action_rect->setShortcut(QKeySequence(Qt::Key_4));
45 | QAction *action_stamp = new QAction(QIcon(":/icons/image.svg"), "图片", this);
46 | action_stamp->setShortcut(QKeySequence(Qt::Key_5));
47 | QAction *action_change_stamp = new QAction(QIcon(":/icons/image.svg"), "换图", this);
48 | action_change_stamp->setShortcut(QKeySequence(Qt::Key_6));
49 | QAction *action_change_color = new QAction(QIcon(":/icons/color.svg"), "换色", this);
50 | action_change_color->setShortcut(QKeySequence(Qt::Key_7));
51 | QAction *action_quit = new QAction(QIcon::fromTheme("application-exit"), "退出", this);
52 | action_quit->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
53 | menu->addAction(action_brush);
54 | menu->addAction(action_line);
55 | menu->addAction(action_ellipse);
56 | menu->addAction(action_rect);
57 | menu->addAction(action_stamp);
58 | menu->addAction(action_change_stamp);
59 | menu->addAction(action_change_color);
60 | menu->addAction(action_quit);
61 |
62 | foreach(QAction *action, menu->actions()){
63 | action->setShortcutVisibleInContextMenu(true);
64 | }
65 |
66 | ui->pushButton_menu->setMenu(menu);
67 | ui->pushButton_menu->setShortcut(QKeySequence(Qt::Key_M));
68 | connect(action_brush, SIGNAL(triggered()), this, SLOT(setBrush()));
69 | connect(action_line, SIGNAL(triggered()), this, SLOT(setLine()));
70 | connect(action_ellipse, SIGNAL(triggered()), this, SLOT(setEllipse()));
71 | connect(action_rect, SIGNAL(triggered()), this, SLOT(setRect()));
72 | connect(action_stamp, SIGNAL(triggered()), this, SLOT(setStamp()));
73 | connect(action_change_stamp, SIGNAL(triggered()), this, SLOT(changeStamp()));
74 | connect(action_change_color, SIGNAL(triggered()), this, SLOT(changeColor()));
75 | connect(action_quit, SIGNAL(triggered()), qApp, SLOT(quit()));
76 | connect(new QShortcut(QKeySequence(Qt::Key_Plus), this), SIGNAL(activated()), this, SLOT(addPenWidth()));
77 | connect(new QShortcut(QKeySequence(Qt::Key_Equal), this), SIGNAL(activated()), this, SLOT(addPenWidth()));
78 | connect(new QShortcut(QKeySequence(Qt::Key_Minus), this), SIGNAL(activated()), this, SLOT(reducePenWidth()));
79 | }
80 |
81 | MainWindow::~MainWindow()
82 | {
83 | delete ui;
84 | }
85 |
86 | void MainWindow::mousePressEvent(QMouseEvent *e)
87 | {
88 | startPnt = e->pos();
89 | endPnt = e->pos();
90 | if(e->buttons() & Qt::LeftButton){
91 | switch(draw_type){
92 | case TEXT_DRAW:
93 | case ERASE_DRAW:
94 | case STAMP_DRAW:
95 | draw(image_temp);
96 | image = image_temp;
97 | }
98 | }else if(e->buttons() & Qt::RightButton) {
99 | clear();
100 | }
101 | }
102 |
103 | void MainWindow::mouseMoveEvent(QMouseEvent *e)
104 | {
105 | if(e->buttons() & Qt::LeftButton){
106 | if (draw_type == BRUSH_DRAW) startPnt = endPnt;
107 | endPnt = e->pos();
108 | if (draw_type == BRUSH_DRAW) {
109 | image = image_temp;
110 | } else {
111 | image_temp = image;
112 | }
113 | draw(image_temp);
114 | }
115 | }
116 |
117 | void MainWindow::mouseReleaseEvent(QMouseEvent *e)
118 | {
119 | Q_UNUSED(e);
120 | image = image_temp;
121 | }
122 |
123 | void MainWindow::paintEvent(QPaintEvent *)
124 | {
125 | QPainter painter(this);
126 | painter.drawImage(0, 0, image_temp);
127 | }
128 |
129 | void MainWindow::draw(QImage &img)
130 | {
131 | QPainter painter(&img);
132 | painter.setPen(pen);
133 | painter.setBrush(brush);
134 | painter.setRenderHint(QPainter::Antialiasing, true);
135 | switch(draw_type){
136 | case BRUSH_DRAW:
137 | painter.drawLine(startPnt, endPnt);
138 | break;
139 | case LINE_DRAW:
140 | painter.drawLine(startPnt, endPnt);
141 | break;
142 | case ARROW_DRAW:{
143 | //if(boolFill){
144 | // painter.setBrush(brush);
145 | //}else{
146 | painter.setBrush(QBrush(Qt::transparent,Qt::SolidPattern));
147 | //}
148 | //if(!boolBorder){
149 | pen.setColor(Qt::transparent);
150 | //}
151 | QPen pena = pen;
152 | pena.setWidth(1);
153 | painter.setPen(pena);
154 | float pi = 3.14;
155 | float a = pi/9;
156 | float l = sqrt(pow(endPnt.y() - startPnt.y(),2) + pow(endPnt.x() - startPnt.x(),2));
157 | float b = asin((endPnt.y() - startPnt.y())/l);
158 | int LW = pen.width();
159 | float x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6,l56;
160 | l56 = LW/2;
161 | float d = (l56 + LW/2)/sin(a);
162 | if (startPnt.x() > endPnt.x()) {
163 | x1 = startPnt.x() - LW/2*sin(b);
164 | x2 = startPnt.x() + LW/2*sin(b);
165 | x4 = endPnt.x() + d*cos(b-a);
166 | x3 = x4 - l56*sin(b);
167 | x5 = endPnt.x() + d*cos(a + b);
168 | x6 = x5 + l56*sin(b);
169 | } else {
170 | x1 = startPnt.x() + LW/2*sin(b);
171 | x2 = startPnt.x() - LW/2*sin(b);
172 | x4 = endPnt.x() - d*cos(b-a);
173 | x3 = x4 + l56*sin(b);
174 | x5 = endPnt.x() - d*cos(a+b);
175 | x6 = x5 - l56*sin(b);
176 | }
177 | y1 = startPnt.y() - LW/2*cos(b);
178 | y2 = startPnt.y() + LW/2*cos(b);
179 | y5 = endPnt.y() - d*sin(a+b);
180 | y6 = y5 + l56*cos(b);
181 | y4 = endPnt.y() - d*sin(b-a);
182 | y3 = y4 - l56*cos(b);
183 | QPointF points[7] = {
184 | QPointF(x1,y1),
185 | QPointF(x2,y2),
186 | QPointF(x3,y3),
187 | QPointF(x4,y4),
188 | QPointF(endPnt),
189 | QPointF(x5,y5),
190 | QPointF(x6,y6)
191 | };
192 | painter.drawPolygon(points,7);
193 | break;}
194 | case RECT_DRAW:{
195 | painter.setBrush(QBrush(Qt::transparent, Qt::SolidPattern));
196 | QRect rect(startPnt,endPnt);
197 | painter.drawRect(rect);
198 | break;}
199 | case SELECT_DRAW:{
200 | painter.setPen(QPen(Qt::black,1,Qt::DashLine));
201 | painter.setBrush(QBrush(Qt::transparent, Qt::SolidPattern));
202 | QRect rect(startPnt, endPnt);
203 | painter.drawRect(rect);
204 | break;}
205 | case ELLIPSE_DRAW:{
206 | QRect rect(startPnt,endPnt);
207 | painter.setBrush(QBrush(Qt::transparent,Qt::SolidPattern));
208 | painter.drawEllipse(rect);
209 | break;}
210 | case TEXT_DRAW:
211 | //painter.setFont(labelFont->font());
212 | //painter.drawText(startPnt.x(),startPnt.y(),text);
213 | break;
214 | case FILL_DRAW:
215 | break;
216 | case ERASE_DRAW:
217 | //painter.setPen(QPen(Qt::white,1));
218 | //painter.setBrush(QBrush(Qt::white,Qt::SolidPattern));
219 | painter.setBrush(QBrush(brush));
220 | painter.drawEllipse(endPnt.x(),endPnt.y(),20,20);
221 | break;
222 | case DEL_DRAW:{
223 | painter.setPen(QPen(Qt::white, 1, Qt::SolidLine));
224 | painter.setBrush(QBrush(Qt::white, Qt::SolidPattern));
225 | QRect rect(startPnt, endPnt);
226 | painter.drawRect(rect);
227 | painter.setPen(pen);
228 | painter.setBrush(brush);
229 | draw_type = SELECT_DRAW;
230 | break;}
231 | case MOVE_DRAW:
232 | /*
233 | {
234 | QRect target(endPnt,imgmove.size());
235 | QPoint p(0,0);
236 | QRect source(p,imgmove.size());
237 | painter.drawImage(target,imgmove,source);
238 | break;
239 | }
240 | */
241 | case COLORPICKER_DRAW:{
242 | QRgb RGB = image_temp.pixel(startPnt.x(),startPnt.y());
243 | pen.setColor(RGB);
244 | brush.setColor(RGB);
245 | painter.setBrush(brush);
246 | break;}
247 | case STAMP_DRAW:
248 | painter.drawPixmap(startPnt, pixmap_stamp);
249 | break;
250 | }
251 | update();
252 | }
253 |
254 | void MainWindow::setBrush()
255 | {
256 | draw_type = BRUSH_DRAW;
257 | drawCursor();
258 | }
259 |
260 | void MainWindow::setLine()
261 | {
262 | draw_type = LINE_DRAW;
263 | drawCursor();
264 | }
265 |
266 | void MainWindow::setEllipse()
267 | {
268 | draw_type = ELLIPSE_DRAW;
269 | drawCursor();
270 | }
271 |
272 | void MainWindow::setRect()
273 | {
274 | draw_type = RECT_DRAW;
275 | drawCursor();
276 | }
277 |
278 | void MainWindow::setStamp()
279 | {
280 | if (pixmap_stamp.isNull()) {
281 | changeStamp();
282 | }else {
283 | QPixmap pixmap_cursor;
284 | if(pixmap_stamp.width()>100 || pixmap_stamp.height()>100)
285 | pixmap_cursor = pixmap_stamp.scaled(100,100,Qt::KeepAspectRatio,Qt::SmoothTransformation);
286 | setCursor(QCursor(pixmap_cursor, 0, 0));
287 | draw_type = STAMP_DRAW;
288 | }
289 | }
290 |
291 | void MainWindow::changeStamp()
292 | {
293 | if(path == "") path = ".";
294 | path = QFileDialog::getOpenFileName(this,"打开图片", path, "图片文件(*.jpg *.jpeg *.png *.bmp *.svg *.gif)");
295 | qDebug() << path;
296 | if(path.length() != 0){
297 | pixmap_stamp.load(path);
298 | setStamp();
299 | }
300 | }
301 |
302 | void MainWindow::changeColor()
303 | {
304 | color = QColorDialog::getColor(color, this);
305 | if (color.isValid()) {
306 | pen.setColor(color);
307 | drawCursor();
308 | }
309 | }
310 |
311 | void MainWindow::clear()
312 | {
313 | image_temp = QImage(QApplication::desktop()->width(), QApplication::desktop()->height(), QImage::Format_ARGB32);
314 | image_temp.fill(Qt::transparent);
315 | image = image_temp;
316 | update();
317 | }
318 |
319 | void MainWindow::addPenWidth()
320 | {
321 | if (pen.width() < 15) {
322 | pen.setWidth(pen.width() + 1);
323 | if (draw_type != BRUSH_DRAW) drawCursor();
324 | }
325 | }
326 |
327 | void MainWindow::reducePenWidth()
328 | {
329 | if (pen.width() > 1) {
330 | pen.setWidth(pen.width() - 1);
331 | if (draw_type != BRUSH_DRAW) drawCursor();
332 | }
333 | }
334 |
335 | void MainWindow::drawCursor()
336 | {
337 | QPixmap pixmap(32,32);
338 | pixmap.fill(Qt::transparent);
339 | QPainter painter(&pixmap);
340 | painter.setRenderHint(QPainter::Antialiasing, true);
341 | painter.setPen(pen);
342 | switch(draw_type){
343 | case BRUSH_DRAW:{
344 | painter.drawPixmap(0,0,QPixmap(":/icons/brush.png"));
345 | QPen penc(pen.color());
346 | painter.setPen(penc);
347 | painter.setBrush(QBrush(pen.color()));
348 | int d = 3;
349 | QPolygon polygon;
350 | polygon << QPoint(0, pixmap.height() - d) << QPoint(d + 1, pixmap.height() - 2*d - 1) << QPoint(2*d + 1, pixmap.height() - d - 1) << QPoint(d, pixmap.height());
351 | painter.drawPolygon(polygon);
352 | break;}
353 | case LINE_DRAW:
354 | painter.drawLine(32,0,0,32);
355 | break;
356 | case RECT_DRAW:
357 | painter.drawRect(2,8,28,20);
358 | break;
359 | case ELLIPSE_DRAW:
360 | painter.drawEllipse(2,2,27,16);
361 | break;
362 | }
363 | setCursor(QCursor(pixmap, 0, pixmap.height()));
364 | }
--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | namespace Ui {
9 | class MainWindow;
10 | }
11 |
12 | class MainWindow : public QMainWindow
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit MainWindow(QWidget *parent = 0);
18 | ~MainWindow();
19 |
20 | protected:
21 | void paintEvent(QPaintEvent *);
22 |
23 | private:
24 | Ui::MainWindow *ui;
25 | enum /*定义图形的类型 */
26 | {
27 | NONE_DRAW,
28 | BRUSH_DRAW,
29 | LINE_DRAW,
30 | ARROW_DRAW,
31 | RECT_DRAW,
32 | ELLIPSE_DRAW,
33 | TEXT_DRAW,
34 | FILL_DRAW,
35 | ERASE_DRAW,
36 | MOVE_DRAW,
37 | SELECT_DRAW,
38 | CLIP_DRAW,
39 | DEL_DRAW,
40 | COLORPICKER_DRAW,
41 | STAMP_DRAW
42 | } draw_type;
43 | QPoint startPnt; //起点
44 | QPoint endPnt; //终点
45 | QImage image, image_temp;
46 | QPixmap pixmap_stamp;
47 | QPen pen;
48 | QBrush brush;
49 | QColor color;
50 | QString path;
51 | void mousePressEvent(QMouseEvent *e);
52 | void mouseMoveEvent(QMouseEvent *e);
53 | void mouseReleaseEvent(QMouseEvent *e);
54 | void draw(QImage &img);
55 | void drawCursor();
56 |
57 | private slots:
58 | void setBrush();
59 | void setLine();
60 | void setEllipse();
61 | void setRect();
62 | void setStamp();
63 | void changeStamp();
64 | void changeColor();
65 | void clear();
66 | void addPenWidth();
67 | void reducePenWidth();
68 | };
69 |
70 | #endif // MAINWINDOW_H
71 |
--------------------------------------------------------------------------------
/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 |
19 |
20 | 360
21 | 260
22 | 32
23 | 32
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | :/icons/icon.png:/icons/icon.png
32 |
33 |
34 |
35 | 32
36 | 32
37 |
38 |
39 |
40 | false
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/res.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | icons/icon.png
4 | icons/brush.png
5 | icons/line.svg
6 | icons/rect.svg
7 | icons/trash.svg
8 | icons/quit.svg
9 | icons/ellipse.svg
10 | icons/image.svg
11 | icons/color.svg
12 |
13 |
14 |
--------------------------------------------------------------------------------