Last Updated on 2021-05-16 by Clay
我一直都想要嘗試看看使用 Python 當中的 PyQt5 製作一個簡單的手寫板,可以任意在我們開發的界面上寫字、畫畫。這可以讓我繼續往下開發許多想要做的項目,比如說:擷取圖片上再次畫圖強調重點、MNIST 的手寫辨識板 —— 後者可以讓我們任意寫入數字,然後由我們訓練好的模型判斷是哪個數字,我覺得這還滿有趣的,也看過有人做過。
於是,我今天便開始嘗試如何製作一個簡單的繪圖板、手寫版。費了好一番功夫,這才終於搞定重寫那些 PyQt5 跟滑鼠相關的 method。
如果對於學習 PyQt5 有興趣,可以看我之前寫過的 PyQt5 教學系列。
如果想要看 PyQt5 官方的指南,可以參考這裡: https://www.riverbankcomputing.com/static/Docs/PyQt5/index.html?highlight=qicon
以下就開始紀錄我怎麼製作這個簡單的繪圖板,程式碼甚至不到百行。
繪圖板設計
會重寫的 PyQt5 滑鼠事件有以下這 3 種:
- mousePressEvent(): 滑鼠按下去的事件
- mouseMoveEvent(): 滑鼠移動的事件
- mouseReleaseEvent(): 滑鼠放開的事件
基本上,我的設計思路是這樣:
這是我們的界面。
當『滑鼠按下去』的時候,我們紀錄起點。
然後我們紀錄『滑鼠的移動』,將紀錄的每個點畫成圖形,然後在『滑鼠放開』的時候結束繪圖。
然後,將這段軌跡,從『起點』到『終點』全部儲存在一個 List 當中,以後若有新增筆劃,就在現有 List 的軌跡之上,新增新的繪圖軌跡。
程式碼
# -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * class MainWindow(QWidget): def __init__(self): super(MainWindow, self).__init__() self.resize(500, 500) self.setWindowTitle('Painter Board') self.tracing_xy = [] self.lineHistory = [] self.pen = QPen(Qt.black, 10, Qt.SolidLine) def paintEvent(self, QPaintEvent): self.painter = QPainter() self.painter.begin(self) self.painter.setPen(self.pen) start_x_temp = 0 start_y_temp = 0 if self.lineHistory: for line_n in range(len(self.lineHistory)): for point_n in range(1, len(self.lineHistory[line_n])): start_x, start_y = self.lineHistory[line_n][point_n-1][0], self.lineHistory[line_n][point_n-1][1] end_x, end_y = self.lineHistory[line_n][point_n][0], self.lineHistory[line_n][point_n][1] self.painter.drawLine(start_x, start_y, end_x, end_y) for x, y in self.tracing_xy: if start_x_temp == 0 and start_y_temp == 0: self.painter.drawLine(self.start_xy[0][0], self.start_xy[0][1], x, y) else: self.painter.drawLine(start_x_temp, start_y_temp, x, y) start_x_temp = x start_y_temp = y self.painter.end() def mousePressEvent(self, QMouseEvent): self.start_xy = [(QMouseEvent.pos().x(), QMouseEvent.pos().y())] def mouseMoveEvent(self, QMouseEvent): self.tracing_xy.append((QMouseEvent.pos().x(), QMouseEvent.pos().y())) self.update() def mouseReleaseEvent(self, QMouseEvent): self.lineHistory.append(self.start_xy+self.tracing_xy) self.tracing_xy = [] if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())ㄘㄟ
程式碼很短,可以直接測試看看。
這裡我貼一張我測試的圖片:
字醜抱歉,滑鼠真心難畫哈哈哈哈。
那個程式碼最後面的ㄘㄟ是?