实例:绘制矩形,出现重影
在画板上绘制矩形
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QPixmap
from PyQt5.QtCore import Qt, QPoint
class Winform(QWidget):
def __init__(self, parent=None):
super(Winform, self).__init__(parent)
self.setWindowTitle("绘制矩形例子")
self.pix = QPixmap()
self.lastPoint = QPoint()
self.endPoint = QPoint()
self.initUi()
def initUi(self):
# 窗口大小设置为600*500
self.resize(600, 500)
# 画布大小为400*400,背景为白色
self.pix = QPixmap(400, 400)
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
pp=QPainter(self.pix)
#指定位置绘制矩形
pp.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()
def mouseReleaseEvent(self, event):
# 鼠标左键释放
if event.button() == Qt.LeftButton:
self.endPoint = event.pos()
# 进行重新绘制
self.update()
if __name__ == "__main__":
app = QApplication(sys.argv)
form = Winform()
form.show()
sys.exit(app.exec_())
运行结果如下
思路分析
在这个例子中,首先将图形绘制在画布上,然后将画布绘制到窗口中
重构painEvent()函数,在函数中添加初始化代码,就是通过lastPoint和endPoint两个点来确定所要绘制矩形的起点,宽度与高度
运行程序,使用鼠标拖出一个矩形,发现出现了很多重影,为u什么会有重影呢?
可以尝试分别快速和慢速的拖动鼠标来绘制矩形,结果发现,拖动速度越快重影越少,其实,鼠标拖动的过程中,屏幕已经刷新很多次了,也可以理解为paintEvent()函数执行了多次,每执行一次就会绘制一个矩形,知道了原因,就可以想办法解决问题了
实例二:双缓冲绘制矩形
import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Winform(QWidget):
def __init__(self,parent=None):
super(Winform, self).__init__(parent)
self.setWindowTitle('双缓存绘图例子')
#主画布
self.pix=QPixmap()
self.lastPoint=QPoint()
self.endPoint=QPoint()
#辅助画布
self.tempix=QPixmap()
#标志:当前是否在画图
self.isDrawing=False
self.initUI()
def initUI(self):
#设置窗口大小:600*500
self.resize(600,500)
#设置画布大小:400*400
self.pix=QPixmap(400,400)
#画布背景颜色填充:白色
self.pix.fill(Qt.white)
#重构paintEvent函数
def paintEvent(self, QPaintEvent):
painter=QPainter(self)
#矩形的属性
x=self.lastPoint.x()
y=self.lastPoint.y()
w=self.endPoint.x()-x
h=self.endPoint.y()-y
#如果正在绘图,就在辅助画布上绘制
if self.isDrawing:
#将之前pix中的内容复制到tempix中,保证以前的内容不消失
self.tempix=self.pix
pp=QPainter(self.tempix)
#绘制矩形在画布
pp.drawRect(x,y,w,h)
#重新绘制画布到窗口
painter.drawPixmap(0,0,self.tempix)
else:
pp=QPainter(self.pix)
pp.drawRect(x,y,w,h)
painter.drawPixmap(0,0,self.pix)
def mousePressEvent(self, QMouseEvent):
#按下鼠标左键
if QMouseEvent.button()==Qt.LeftButton:
#获得鼠标的属性值,x,y坐标值
self.lastPoint=QMouseEvent.pos()
# print(self.lastPoint)
self.endPoint=self.lastPoint
self.isDrawing=True
def mouseReleaseEvent(self, QMouseEvent):
#释放鼠标左键
if QMouseEvent.button()==Qt.LeftButton:
self.endPoint=QMouseEvent.pos()
#进行重新绘制
self.update()
self.isDrawing=False
if __name__ == '__main__':
app=QApplication(sys.argv)
form=Winform()
form.show()
sys.exit(app.exec_())
运行程序,效果如下
代码分析
在这个例子中,按下鼠标左键时标志正在绘图,当释放左键时,则取消正在绘图的标志,运行程序,绘图正常,没有重影
在这个例子中,需要添加一个辅助画布,如果正在绘图,也就是还没有释放鼠标左键时,就在辅助画布上进行,只有释放鼠标左键,才在主画布上绘图
第一组代码:添加两个变量
#辅助画布
self.tempix=QPixmap()
#标志:当前是否在画图
self.isDrawing=False
第二组代码:重构painEvent()函数,如果正在绘图,就在辅助画布上进行,将以前pix中的内容复制到temPix中,保证以前的内容不消失
if self.isDrawing:
#将之前pix中的内容复制到tempix中,保证以前的内容不消失
self.tempix=self.pix
pp=QPainter(self.tempix)
#绘制矩形在画布
pp.drawRect(x,y,w,h)
#重新绘制画布到窗口
painter.drawPixmap(0,0,self.tempix)
else:
pp=QPainter(self.pix)
pp.drawRect(x,y,w,h)
painter.drawPixmap(0,0,self.pix)
第三组代码:重构mousePressEvent()函数,更改鼠标左键按下时处理函数的内容
def mousePressEvent(self, QMouseEvent):
#按下鼠标左键
if QMouseEvent.button()==Qt.LeftButton:
#获得鼠标的属性值,x,y坐标值
self.lastPoint=QMouseEvent.pos()
# print(self.lastPoint)
self.endPoint=self.lastPoint
self.isDrawing=True
第四组代码:重构mouseReleaseEvent()函数,更改鼠标左键释放时处理函数的内容
def mouseReleaseEvent(self, QMouseEvent):
#释放鼠标左键
if QMouseEvent.button()==Qt.LeftButton:
self.endPoint=QMouseEvent.pos()
#进行重新绘制
self.update()
self.isDrawing=False
双缓存技术总结
在这个例子中,要实现使用鼠标在界面上绘制一个任意大小的矩形而不出现重影,需要两个画布,他们都是QPixmap实例,其中tenpPix作为临时缓冲区,当拖动鼠标绘制矩形时,将内容先绘制到tempPix上,然后再将tempix绘制到界面上,pix作为缓冲区,用来保存已经完成的绘制,当释放鼠标左键完成矩形绘制后,则将tempix的内容复制到pix上,为了在绘制时不出现重影,而且保证之前绘制的内容不消失,那么每一次绘制都是在原来的图像上进行的,所以需要在绘制tempix之前,先将pix的内容复制到tempix上,因为这里有两个QPixmap对象,也可以说有两个缓存区,所以称之为双缓冲绘图
相关源码及素材
https://download.csdn.net/download/jia666666/10616087