Qt提供了比较丰富的内置控件,一些常规的开发通常够用。
但是有时,还是需要我们自己开发特殊用途的自定义控件。
比如, 在我们的项目实战3中,要求开发一个模拟充电桩、洗车机等设备的测试工具。
模拟这些设备的控件,就需要我们自己定制开发。
QPainter
我们前面学过的内置控件,比如按钮、输入框、选择框,它们的视觉界面是怎么呈现出来的呢?
其实都是 Qt 画出来的。
Qt是通过 QPainter 类实现画出各种控件的。
QPainter 类对象可以在 任何继承自 QPaintDevice (比如QWidget, QImage, QPixmap )的实例上 绘制 图形、文字
控件的视觉界面,其实就是通过画出各种 线条、矩形、圆形,等这些形状组合出来的。
画线
比如,下面的代码调用 QPainter 对象的 drawLine 方法 画一条线,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from PySide2 import QtGui, QtWidgets
class MyWidget(QtWidgets.QWidget):
def paintEvent(self, e): painter = QtGui.QPainter(self) painter.drawLine(50, 80, 200, 300) painter.end() app = QtWidgets.QApplication() window = QtWidgets.QMainWindow() window.resize(500, 500)
my = MyWidget(window) my.move(0,0) my.resize(500,500)
window.show() app.exec_()
|
画笔指定粗度、颜色
上面的示例中,画线的宽度比较细, 颜色是黑色
如果我们想让画出的线有指定的宽度和颜色,该怎么办?
这是由 QPainter 的画笔属性(pen)决定的
缺省的画笔属性 的宽度为1个像素,颜色为黑色。
我们可以设置 为另外的画笔对象(QPen) 作为 属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class MyWidget(QtWidgets.QWidget):
def paintEvent(self, e): painter = QtGui.QPainter(self)
pen = QtGui.QPen() pen.setWidth(3) pen.setColor(QtGui.QColor('red'))
painter.setPen(pen)
painter.drawLine(50, 80, 200, 300) painter.end()
|
画点
调用 QPainter 对象的 drawPoint 方法可以画一个点,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class MyWidget(QtWidgets.QWidget):
def paintEvent(self, e): painter = QtGui.QPainter(self)
pen = QtGui.QPen() pen.setWidth(10) pen.setColor(QtGui.QColor('red')) painter.setPen(pen)
painter.drawPoint(200, 150) painter.end()
|
画矩形
调用 QPainter 对象的 drawRect 方法可以画一个矩形,如下
1 2 3 4 5 6 7 8 9 10
| class MyWidget(QtWidgets.QWidget):
def paintEvent(self, e): painter = QtGui.QPainter(self)
painter.drawRect(50, 50, 300,300) painter.end()
|
画椭圆
调用 QPainter 对象的 drawEllipse 方法可以画一个椭圆,如下
1 2 3 4 5 6 7 8 9 10 11
| class MyWidget(QtWidgets.QWidget):
def paintEvent(self, e): painter = QtGui.QPainter(self)
painter.drawRect(50, 50, 300,200) painter.drawEllipse(50, 50, 300,200) painter.end()
|
可以想象,如果水平垂直方向直径相同,那就是一个正圆形了。
画刷填充
前面我们画的矩形和椭圆,这些图形内部的颜色没有设置的,和底色一致
如果我们想设定矩形椭圆等图形内部填充的颜色,就要通过 QPainter 的画刷属性(brush) 来设置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| from PySide2 import QtGui, QtWidgets from PySide2.QtCore import Qt
class MyWidget(QtWidgets.QWidget):
def paintEvent(self, e): painter = QtGui.QPainter(self)
brush = QtGui.QBrush() brush.setColor(QtGui.QColor("yellow")) brush.setStyle(Qt.SolidPattern)
painter.setBrush(brush)
painter.drawRect(50, 50, 100,100) painter.drawEllipse(200, 200, 100,100)
painter.end() app = QtWidgets.QApplication()
window = QtWidgets.QMainWindow() window.resize(500, 500)
my = MyWidget(window) my.move(0,0) my.resize(500,500)
window.show() app.exec_()
|
其中
1
| brush.setStyle(Qt.SolidPattern)
|
设定了图形内部的填充样式, SolidPattern 是最常见的填满的风格,还有其它的比如
1 2 3 4 5 6 7
| Dense1Pattern
HorPattern
VerPattern
CrossPattern
|
等等,具体可以参考这里
画文字
我们也可以在控件上绘制文字,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| from PySide2 import QtGui, QtWidgets
class MyWidget(QtWidgets.QWidget):
def paintEvent(self, e): painter = QtGui.QPainter(self)
pen = QtGui.QPen() pen.setWidth(1) pen.setColor(QtGui.QColor('red')) painter.setPen(pen)
font = QtGui.QFont() font.setFamily('黑体') font.setPointSize(30) painter.setFont(font)
painter.drawText(100, 100, 'hello,白月黑羽!')
painter.end() app = QtWidgets.QApplication()
window = QtWidgets.QMainWindow() window.resize(500, 500)
my = MyWidget(window) my.move(0,0) my.resize(500,500)
window.show() app.exec_()
|
自定义控件示例
现在我们可以创建一个真正需要用到的自定义控件了。
在黑羽Elife项目中,要求开发一个模拟充电桩、洗车机设备的测试工具。
下面的示例代码来实现 充电口控件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| from PySide2 import QtGui, QtWidgets
class QOutlet(QtWidgets.QWidget): """ 插座控件 """
def __init__(self,parent, color) -> None: super().__init__(parent) self.color = color self.setMinimumSize(70, 70) self.setMaximumSize(70, 70)
def paintEvent(self, e): painter = QtGui.QPainter(self)
pen = QtGui.QPen() pen.setWidth(1)
pen.setColor(QtGui.QColor(self.color)) painter.setPen(pen) painter.drawRect(0, 0, 60, 60)
pen = QtGui.QPen() pen.setWidth(3) pen.setColor(QtGui.QColor(self.color)) painter.setPen(pen)
painter.drawLine(12,10,12,25) painter.drawLine(30,10,30,25) painter.drawLine(48,10,48,25)
painter.drawLine(10,35,20,50) painter.drawLine(50,35,40,50)
painter.end()
app = QtWidgets.QApplication()
window = QtWidgets.QMainWindow() window.resize(500, 500)
my = QOutlet(window,'green') my.move(0,0)
my = QOutlet(window,'red') my.move(100,0)
my = QOutlet(window,'blue') my.move(200,0)
window.show() app.exec_()
|