Python3使用PyQt5製作簡單的畫板/手寫板例項

Python3使用PyQt5製作簡單的畫板/手寫板例項

1.前言

版本:Python3.6.1 PyQt5

寫一個程式的時候需要用到畫板/手寫板,只需要最簡單的那種。原以為網上到處都是,結果找了好幾天,都沒有找到想要的結果。

網上的要麼是非python版的qt程式(要知道qt版本之間差異巨大,還是非同一語言的),改寫難度太大。要麼是PyQt4的老程式,很多都已經不能在PyQt5上執行了。要麼是大神寫的特別複雜的程式,簡直是直接做出了一個Windows自帶的畫圖版,只能膜拜~

於是我只能在眾多程式碼中慢慢尋找自己需要的那一小部分,然後不斷地拼湊,不斷地理解大神的程式碼,最終做出這麼一個簡單的畫板。望著這個簡單的畫板我真是淚流滿面,中間數十次拼不對拼不全導致程式無數次崩潰,差點就放棄了……

2.簡單的畫板1.0

在簡單的畫板1.0這裡,實現的功能是:在定點和移動中的滑鼠所在處畫一條線
如圖所示:

滑鼠按住移動的話,線也會跟著移動,從這個簡單的程式開始理解PyQt5的執行機制吧。


'''
簡單的畫板1.0
功能:在定點和移動中的滑鼠所在處畫一條線
作者:PyLearn
最後修改日期: 2017/10/18
'''
import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.QtGui import (QPainter, QPen)
from PyQt5.QtCore import Qt
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
#resize設定寬高,move設定位置
self.resize(400, 300)
self.move(100, 100)
self.setWindowTitle("簡單的畫板1.0")
#setMouseTracking設定為False,否則不按下滑鼠時也會跟蹤滑鼠事件
self.setMouseTracking(False)
#設定兩個變數接收移動中的點的x、y座標
self.pos_x = 20
self.pos_y = 20
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
pen = QPen(Qt.black, 2, Qt.SolidLine)
painter.setPen(pen)
#定點(20, 20) 到 (self.pos_x, self.pos_y)之間畫線
painter.drawLine(20, 20, self.pos_x, self.pos_y)
painter.end()
def mouseMoveEvent(self, event):
'''
按住滑鼠移動事件:更新pos_x和pos_y的值
呼叫update()函式在這裡相當於呼叫paintEvent()函式
每次update()時,之前呼叫的paintEvent()留下的痕跡都會清空
'''
self.pos_x = event.pos().x()
self.pos_y = event.pos().y()
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
pyqt_learn = Example()
pyqt_learn.show()
app.exec_()

3.簡單的畫板2.0

從以上的簡單的畫板1.0程式的執行可以發現,按住滑鼠移動的時候,線也會跟著移動,那如何讓之前的線留下痕跡,而不是消失呢?

在簡單的畫板2.0中,使用一個列表儲存所有移動過的點,然後要畫線的時候,迴圈遍歷列表,依次畫出列表中點到定點之間的線即可。

效果如圖所示:


'''
簡單的畫板2.0
功能:
在定點和移動中的滑鼠所在處畫一條線
並將畫過的線都保留在窗體上
作者:PyLearn
最後修改日期: 2017/10/18
'''
import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.QtGui import (QPainter, QPen)
from PyQt5.QtCore import Qt
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
#resize設定寬高,move設定位置
self.resize(400, 300)
self.move(100, 100)
self.setWindowTitle("簡單的畫板2.0")
#setMouseTracking設定為False,否則不按下滑鼠時也會跟蹤滑鼠事件
self.setMouseTracking(False)
'''
要想將畫過的線都保留在窗體上
需要一個列表來儲存所有移動過的點
'''
self.pos_xy = []
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
pen = QPen(Qt.black, 2, Qt.SolidLine)
painter.setPen(pen)
#迴圈遍歷self.pos_xy中每個點,然後畫點到定點之間的線
for pos_tmp in self.pos_xy:
painter.drawLine(20, 20, pos_tmp[0], pos_tmp[1])
painter.end()
def mouseMoveEvent(self, event):
'''
按住滑鼠移動事件:將當前點新增到pos_xy列表中
呼叫update()函式在這裡相當於呼叫paintEvent()函式
每次update()時,之前呼叫的paintEvent()留下的痕跡都會清空
'''
#中間變數pos_tmp提取當前點
pos_tmp = (event.pos().x(), event.pos().y())
#pos_tmp新增到self.pos_xy中
self.pos_xy.append(pos_tmp)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
pyqt_learn = Example()
pyqt_learn.show()
app.exec_()

4.簡單的畫板3.0

好了,接下來進入正題了。簡單的畫板2.0不過是畫滑鼠所在點到定點的線,那麼如何將按住滑鼠後移動的軌跡保留在窗體上?

這個就需要一個列表來儲存所有移動過的點,然後把所有相鄰兩個點之間都畫一條線,就能斷斷續續連成滑鼠的痕跡了。
效果如圖所示:

是不是就畫出滑鼠移動的軌跡了!

不過這也是有缺點的,比如說寫個5看看:

硬生生變成了一個5不是5, 6不是6的數字。這是因為再次提筆畫時,5上面的那一橫跟之前畫的尾巴那裡連起來了。好好想想,這個問題怎麼解決呢?


'''
簡單的畫板3.0
功能:將按住滑鼠後移動的軌跡保留在窗體上
作者:PyLearn
最後修改日期: 2017/10/18
'''
import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.QtGui import (QPainter, QPen)
from PyQt5.QtCore import Qt
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
#resize設定寬高,move設定位置
self.resize(400, 300)
self.move(100, 100)
self.setWindowTitle("簡單的畫板3.0")
#setMouseTracking設定為False,否則不按下滑鼠時也會跟蹤滑鼠事件
self.setMouseTracking(False)
'''
要想將按住滑鼠後移動的軌跡保留在窗體上
需要一個列表來儲存所有移動過的點
'''
self.pos_xy = []
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
pen = QPen(Qt.black, 2, Qt.SolidLine)
painter.setPen(pen)
'''
首先判斷pos_xy列表中是不是至少有兩個點了
然後將pos_xy中第一個點賦值給point_start
利用中間變數pos_tmp遍歷整個pos_xy列表
point_end = pos_tmp
畫point_start到point_end之間的線
point_start = point_end
這樣,不斷地將相鄰兩個點之間畫線,就能留下滑鼠移動軌跡了
'''
if len(self.pos_xy) > 1:
point_start = self.pos_xy[0]
for pos_tmp in self.pos_xy:
point_end = pos_tmp
painter.drawLine(point_start[0], point_start[1], point_end[0], point_end[1])
point_start = point_end
painter.end()
def mouseMoveEvent(self, event):
'''
按住滑鼠移動事件:將當前點新增到pos_xy列表中
呼叫update()函式在這裡相當於呼叫paintEvent()函式
每次update()時,之前呼叫的paintEvent()留下的痕跡都會清空
'''
#中間變數pos_tmp提取當前點
pos_tmp = (event.pos().x(), event.pos().y())
#pos_tmp新增到self.pos_xy中
self.pos_xy.append(pos_tmp)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
pyqt_learn = Example()
pyqt_learn.show()
app.exec_()

5.簡單的畫板4.0

簡單的畫板3.0中有一個致命的問題,那就是連續的問題,比如說要寫一個三位數123:

很難看對不對?

解決這個問題的方法應該是有很多種的,我也沒有深入想,就直接用了這個麻煩點的方法。

我的辦法是當滑鼠按住移動然後鬆開的時候,往儲存所有移動過的點的列表中新增一個斷點(-1, -1)。然後在每次畫線的時候,都判斷一下是不是斷點,如果是斷點的話就想辦法跳過去,並且不連續的開始接著畫線。

效果如圖所示:

以下是具體實現程式碼:


'''
簡單的畫板4.0
功能:
將按住滑鼠後移動的軌跡保留在窗體上
並解決二次作畫時與上次痕跡連續的問題
作者:PyLearn
最後修改日期: 2017/10/18
'''
import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.QtGui import (QPainter, QPen)
from PyQt5.QtCore import Qt
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
#resize設定寬高,move設定位置
self.resize(400, 300)
self.move(100, 100)
self.setWindowTitle("簡單的畫板4.0")
#setMouseTracking設定為False,否則不按下滑鼠時也會跟蹤滑鼠事件
self.setMouseTracking(False)
'''
要想將按住滑鼠後移動的軌跡保留在窗體上
需要一個列表來儲存所有移動過的點
'''
self.pos_xy = []
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
pen = QPen(Qt.black, 2, Qt.SolidLine)
painter.setPen(pen)
'''
首先判斷pos_xy列表中是不是至少有兩個點了
然後將pos_xy中第一個點賦值給point_start
利用中間變數pos_tmp遍歷整個pos_xy列表
point_end = pos_tmp
判斷point_end是否是斷點,如果是
point_start賦值為斷點
continue
判斷point_start是否是斷點,如果是
point_start賦值為point_end
continue
畫point_start到point_end之間的線
point_start = point_end
這樣,不斷地將相鄰兩個點之間畫線,就能留下滑鼠移動軌跡了
'''
if len(self.pos_xy) > 1:
point_start = self.pos_xy[0]
for pos_tmp in self.pos_xy:
point_end = pos_tmp
if point_end == (-1, -1):
point_start = (-1, -1)
continue
if point_start == (-1, -1):
point_start = point_end
continue
painter.drawLine(point_start[0], point_start[1], point_end[0], point_end[1])
point_start = point_end
painter.end()
def mouseMoveEvent(self, event):
'''
按住滑鼠移動事件:將當前點新增到pos_xy列表中
呼叫update()函式在這裡相當於呼叫paintEvent()函式
每次update()時,之前呼叫的paintEvent()留下的痕跡都會清空
'''
#中間變數pos_tmp提取當前點
pos_tmp = (event.pos().x(), event.pos().y())
#pos_tmp新增到self.pos_xy中
self.pos_xy.append(pos_tmp)
self.update()
def mouseReleaseEvent(self, event):
'''
重寫滑鼠按住後鬆開的事件
在每次鬆開後向pos_xy列表中新增一個斷點(-1, -1)
然後在繪畫時判斷一下是不是斷點就行了
是斷點的話就跳過去,不與之前的連續
'''
pos_test = (-1, -1)
self.pos_xy.append(pos_test)
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
pyqt_learn = Example()
pyqt_learn.show()
app.exec_()

至此,終於完成了簡單的畫板程式的實現!

另外,如果在使用這個程式碼的過程中有遇到什麼問題,也歡迎向我反饋。

以上這篇Python3使用PyQt5製作簡單的畫板/手寫板例項就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援指令碼之家。

您可能感興趣的文章:

python3 PyQt5實現自定義視窗部件Counterspython3 PyQt5實現支援多執行緒的頁面索引器應用程式python3 PyQt5 Qt Designer實現擴充套件對話方塊python3 PyQt5 Qt Designer實現堆疊視窗部件python3 PyQt5重新實現QT事件處理程式python3 PyQt5重新實現自定義資料拖放處理python3使用pyqt5製作一個超簡單瀏覽器的例項python3.5 PyQt5 Eric6 實現的一個計算器程式碼python3 PyQt5實現使用剪貼簿做複製與粘帖示例python3 PyQt5圖形項的自定義和互動 python3實現page Designer應用程式