Skip to content

[PyQt5] 透過程式製作簡易繪圖板

我一直都想要嘗試看看使用 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_())ㄘㄟ



程式碼很短,可以直接測試看看。

這裡我貼一張我測試的圖片:

字醜抱歉,滑鼠真心難畫哈哈哈哈。

1 thought on “[PyQt5] 透過程式製作簡易繪圖板”

Leave a Reply