├── 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 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /icons/ellipse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonichy/HTYScreenPen/6a71a794184ddaa5cdc4c389881cdd7610c8c1b8/icons/icon.png -------------------------------------------------------------------------------- /icons/image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /icons/line.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /icons/quit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /icons/rect.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /icons/trash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 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 | --------------------------------------------------------------------------------