PyQt5之绘图
在PyQt中常用的图像类有4个,即QPixmap、QImage、QPicture和QBitmap。
QPixmap
是专门为绘图而设计的,在绘制图片时需要使用QPixmap;QImage
提供了一个与硬件无关的图像表示函数,可以用于图片的像素级访问;QPicture
是一个绘图设备类,它继承自QPainter类,可以使用QPainter的begin()函数在QPicture上绘图,使用end()函数结束绘图,使用QPicture的save()函数将QPainter所使用过的绘图指令保存到文件中;QBitmap
是一个继承自QPixmap的简单类,它提供了1bit深度的二值图像的类,QBitmap提供的单色图像可以用来制作游标(QCursor)或者笔刷(QBrush)。
一、简单绘图
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Demo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('简单绘图')
self.pix = QPixmap()
self.lastPoint = QPoint()
self.endPoint = QPoint()
self.initUI()
def initUI(self):
self.resize(600, 500)
self.pix = QPixmap(600, 500) # 设置画布大小
self.pix.fill(Qt.white) # 设置画布背景颜色为白色
# 绘图
def paintEvent(self, event):
p = QPainter(self.pix)
p.drawLine(self.lastPoint, self.endPoint) # 根据鼠标指针前后两个位置绘制直线
self.lastPoint = self.endPoint # 让前一个坐标值等于后一个坐标值,就能画出连续的线
painter = QPainter(self)
painter.drawPixmap(0, 0, self.pix)
#当鼠标左键按下时触发该函数
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.lastPoint = event.pos()
self.endPoint = self.lastPoint
#当鼠标左键移动时触发该函数
def mouseMoveEvent(self, event):
if event.buttons() and Qt.LeftButton:
self.endPoint = event.pos()
self.update()#调用paintEvent函数,重新绘制
#当鼠标左键释放时触发该函数
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.endPoint = event.pos()
self.update() # 调用paintEvent函数,重新绘制
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Demo()
form.show()
sys.exit(app.exec_())
运行效果如下:
注:在重构mouseMoveEvent函数时,buttons()函数可以获取鼠标指针移动过程中按下的所有按键,然后用Qt.LeftButton来判断是否按下了左键,必须使用该函数来判断按下鼠标的按键。
二、双缓冲绘图
- 绘制矩形,出现重影:
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Demo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('绘制矩形,出现重影')
self.pix = QPixmap()
self.lastPoint = QPoint()
self.endPoint = QPoint()
self.initUI()
def initUI(self):
self.resize(600, 500)
self.pix = QPixmap(600, 500) # 设置画布大小
self.pix.fill(Qt.white) # 设置画布背景颜色为白色
# 绘图
def paintEvent(self, event):
p = QPainter(self.pix)
painter = QPainter(self)
x = self.lastPoint.x()
y = self.lastPoint.y()
w = self.endPoint.x()-x
h = self.endPoint.y()-y
p.drawRect(x,y,w,h)
painter.drawPixmap(0, 0, self.pix)
#当鼠标左键按下时触发该函数
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.lastPoint = event.pos()
self.endPoint = self.lastPoint
#当鼠标左键移动时触发该函数
def mouseMoveEvent(self, event):
if event.buttons() and Qt.LeftButton:
self.endPoint = event.pos()
self.update()#调用paintEvent函数,重新绘制
#当鼠标左键释放时触发该函数
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.endPoint = event.pos()
self.update() # 调用paintEvent函数,重新绘制
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Demo()
form.show()
sys.exit(app.exec_())
运行效果如下:
注:其实,在拖动鼠标的过程中屏幕已经刷新了很多次,即paintEvent函数执行了很多次,每执行一次就会绘制一个矩形,拖动速度越快,重影越少。
- 使用双缓冲技术绘制矩形,避免出现重影:
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Demo(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('使用双缓冲技术绘制矩形,避免出现重影')
self.pix = QPixmap()
self.lastPoint = QPoint()
self.endPoint = QPoint()
self.temPix = QPixmap()#辅助画布
self.isDrawing = False #标志是否正在绘图
self.initUI()
def initUI(self):
self.resize(600, 500)
self.pix = QPixmap(600, 500) # 设置画布大小
self.pix.fill(Qt.white) # 设置画布背景颜色为白色
# 绘图
def paintEvent(self, event):
painter = QPainter(self)
x = self.lastPoint.x()
y = self.lastPoint.y()
w = self.endPoint.x()-x
h = self.endPoint.y()-y
#如果正在绘图,就在辅助画布上绘制
if self.isDrawing:
self.temPix = self.pix #将以前pix中的内容复制到辅助画布中,保证以前的内容不消失
p = QPainter(self.temPix)
p.drawRect(x,y,w,h)
painter.drawPixmap(0, 0, self.pix)
else:
p = QPainter(self.pix)
p.drawRect(x, y, w, h)
painter.drawPixmap(0, 0, self.pix)
#当鼠标左键按下时触发该函数
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.lastPoint = event.pos()
self.endPoint = self.lastPoint
self.isDrawing = True
#当鼠标左键释放时触发该函数
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.endPoint = event.pos()
self.update() # 调用paintEvent函数,重新绘制
self.isDrawing = False
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Demo()
form.show()
sys.exit(app.exec_())
运行效果如下:
双缓冲技术总结:
在这个例子中,要实现使用鼠标在界面上绘制一个任意大小的矩形而不出现重影,需要两个画布,其中一个作为临时缓冲区。为了在绘制时不出现重影,而且保证以前绘制的内容不消失,那么每一次绘制都是在原来的图形上进行的,所以需要绘制在辅助画布之前,先将pix的内容复制到辅助画布上。