笔者在陆文周老师主编的《Qt5开发及实例》中看到了一个基础绘图实例,涵盖了Qt5的基本绘图方法,感觉对Qt绘图入门非常有帮助,故用PyQt5重写了一遍,记录在此。
老规矩,先上成品图。
由于博客支持的GIF最大不超过5M,而完整演示所有操作生成的GIF远大于允许的size,因此GIF仅简单演示基本操作,笔者再贴几张截图作为补充。
可以看到,该项目涵盖了PyQt5的基本绘图方法,包括形状的绘制,画笔的设置,填充方案的选择等。开发者可以根据这些基本绘图方法绘制出更为复杂的图像。
在此不再赘述控件的布局方法,仅给出ComboBox 控件的设置。在此以形状和画笔颜色设置为例:
# 设置形状ComboBox
self.shapeLabel = QtWidgets.QLabel("形状: ") # label的初始化
self.shapeComboBox = QtWidgets.QComboBox() # ComboBox的初始化
self.shapeComboBox.addItem("Line", 0) # ComboBox添加项目
self.shapeComboBox.addItem("Rectangle", 1)
self.shapeComboBox.addItem("RoundedRect", 2)
self.shapeComboBox.addItem("Ellipse", 3)
self.shapeComboBox.addItem("Polygon", 4)
self.shapeComboBox.addItem("Polyline", 5)
self.shapeComboBox.addItem("Points", 6)
self.shapeComboBox.addItem("Arc", 7)
self.shapeComboBox.addItem("Path", 8)
self.shapeComboBox.addItem("Text", 9)
self.shapeComboBox.addItem("Pixmap", 10)
self.shapeComboBox.activated[int].connect(self.showShape) # 绑定槽函数self.showShape()。当下拉选项被激发,则发送类型为int型的信号。
# 以画笔颜色为例
self.penColorLabel = QtWidgets.QLabel("画笔颜色:") # 画笔颜色label
self.penColorFrame = QtWidgets.QFrame() # label左侧显示画笔当前颜色的矩形,是个QFrame()
self.penColorFrame.setFrameStyle(QtWidgets.QFrame.Panel|QtWidgets.QFrame.Sunken) # 设置QFrame的形状样式
self.penColorFrame.setAutoFillBackground(True) # 背景填充为True
self.penColorFrame.setPalette(QtGui.QPalette(QtCore.Qt.black)) # 默认为黑色
self.penColorBtn = QtWidgets.QPushButton("更改")
self.penColorBtn.clicked.connect(self.showPenColor) # button连接槽函数更改pen的颜色
接上,仍以形状和画笔颜色的ComboBox 为例,编写self.showShape() 和self.showPenColor()
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
self.paintArea = PaintArea()
......
def showShape(self, value): # value即为ComboBox选项被activated时所发射的,带有int参数的信号
shape = Shape[self.shapeComboBox.itemData(value, QtCore.Qt.UserRole)]
self.paintArea.setShape(shape) # 调用setShape函数重绘
#在ColorDialog中改变颜色,然后得到当前的画笔颜色,线粗,线类型,笔帽,笔连接类型,再执行setPen重绘shape
def showPenColor(self):
color = QtWidgets.QColorDialog.getColor(QtCore.Qt.blue) # 默认值为blue。当在ColorDialog中选定新的颜色并按下OK后,color变为新选定的颜色。
self.penColorFrame.setPalette(QtGui.QPalette(color))
value = self.penWidthSpinBox.value() # 线宽由SpinBox控件控制
style = QtCore.Qt.PenStyle(self.penStyleComboBox.itemData(self.penStyleComboBox.currentIndex(),
QtCore.Qt.UserRole))
cap = QtCore.Qt.PenCapStyle(self.penCapComboBox.itemData(self.penCapComboBox.currentIndex(),
QtCore.Qt.UserRole))
join = QtCore.Qt.PenJoinStyle(self.penJoinComboBox.itemData(self.penJoinComboBox.currentIndex(),
QtCore.Qt.UserRole))
self.paintArea.setPen(QtGui.QPen(color, value, style, cap, join))
Shape = ["Line", "Rectangle", "RoundRect", "Ellipse",
"Polygon","Polyline", "Points", "Arc", "Path",
"Text", "Pixmap"]
class PaintArea(QtWidgets.QWidget):
def __init__(self):
super(PaintArea, self).__init__()
......
def setShape(self, shape):
self.shape = shape
self.update() # 重绘
def setPen(self, pen):
self.pen = pen
self.update() # 重绘
该部分涉及到用Qt绘制各种形状的函数。绝大多数函数的语法是和Qt5完全一样的,但有少部分传参规则不同:
def paintEvent(self, event):
p = QtGui.QPainter(self)
p.setPen(self.pen)
p.setBrush(self.brush)
rect = QtCore.QRect(50, 100, 300, 200)
points = [QtCore.QPoint(150, 100),
QtCore.QPoint(300, 150),
QtCore.QPoint(350, 250),
QtCore.QPoint(100, 300)]
startAngle = 30 * 16 # 弧的起始角和跨度。30°起,正向跨120°。
spanAngle = 120 * 16
path = QtGui.QPainterPath()
path.addRect(150, 150, 100, 100)
path.moveTo(100, 100)
path.cubicTo(300, 100, 200, 200, 300, 300) # cubicTo(c1, c2, endPoint):绘制贝塞尔曲线
path.cubicTo(100, 300, 200, 200, 100, 100)
path.setFillRule(self.fillRule) # 填充规则
if self.shape == Shape[0]:
p.drawLine(rect.topLeft(), rect.bottomRight()) # 从rect左上角到右下角画直线
elif self.shape == Shape[1]:
p.drawRect(rect) # 画矩形
elif self.shape == Shape[2]:
p.drawRoundedRect(rect, 20, 20) #画圆角矩形,(rect, 圆角水平半径,圆角竖直半径)
elif self.shape == Shape[3]:
p.drawEllipse(rect) # 画椭圆
elif self.shape == Shape[4]:
p.drawPolygon(QtGui.QPolygon(points)) #画折线
elif self.shape == Shape[5]:
p.drawPolyline(QtGui.QPolygon(points)) # 画多边形(折线封闭)
elif self.shape == Shape[6]:
p.drawPoints(QtGui.QPolygon(points)) # 画点
elif self.shape == Shape[7]:
p.drawArc(rect, startAngle, spanAngle) # 画弧度
elif self.shape == Shape[8]:
p.drawPath(path) # 画路径
elif self.shape == Shape[9]:
p.drawText(rect, QtCore.Qt.AlignCenter, "Hello Qt!") # 写文字
elif self.shape == Shape[10]:
p.drawPixmap(150, 150, QtGui.QPixmap("sunflower1.jpg")) # 添加图片
else:
return
至此,该项目的几个关键点总结完毕。
PyQt5绝大多数内置的绘图函数,其效果和用法与Qt是相同的。开发者不妨参考Qt5的官方手册,或是PyQt5的官方文档来查看。
PyQt官方文档:QPainter
PyQt官方文档:QPen
PyQt官方文档:QBrush
最后,上海的Qter们,欢迎关注公众号“Qter欢聚在上海”,让我们共同学习,共同成长?