(PyQt5基本窗口控件(十)窗口绘图类控件)

十、窗口绘图类控件

  • 在 PyQt5中,一般可以通过 QPainter,QPen和 QBrush 这三个类来实现绘图功能。此外,QPixmap的作用是加载并呈现本地图像,而图像的呈现本质上也是通过绘图方式实现的,所以 QPixmap也可以被视为绘图的一个类。

1、QPainter

  • QPainter类在 QWidget(控件)上执行绘图操作,它是一个绘制工具,为大部分图形界面提供了高度优化的函数,使QPainter类可以绘制从简单的直线到复杂的饼图等。
  • 绘制操作在 QWidget.paintEvent()中完成。绘制方法必须放在QtGui.QPainter对象的begin()和 end()之间。QPainter类在控件或其他绘图设备上执行较低级别的图形绘制功能。
  • QPainter类中常用的方法
方法 描述
begin() 开始在目标设备上绘制
drawArc() 在起始角度和最终角度之间画弧
drawEllipse 在一个矩形内画一个椭圆
drawLine(int x1, int y1, int x2, int y2) 绘制一条指定了端点坐标的线。绘制从(x1, y1)到(x2, y2)的直线并且设置当前画笔位置为(x2, y2)
drawPixmap() 从图像文件中提取Pixmap并将其显示在指定的位置
drawPolygon() 使用坐标数组绘制多边形
drawRect(int x,int y,int w,int h) 以给定的宽度w和高度h从左上角坐标(x,y)绘制一个矩形
drawText() 显示给定坐标处的文字
fillRect() 使用QColor参数填充矩形
setBrush() 设置画笔风格
setPen() 设置用于绘制的笔的颜色、大小和样式
  • 画笔风格
枚举类型 描述
Qt.NoPen 没有线。比如 QPainter.drawRect()填充,但没有绘制任何边界线
Qt.SolidLine 一条简单的线
Qt.DashLine 由一些像素分隔的短信
Qt.DotLine 由一些像素分隔的点
Qt.DashDotLine 轮流交替的点和短线
Qt.DashDotDotLine 一条短线、两个点
Qt.MPenStyle 画笔风格的掩码

案例二十五 绘制文字

# -*- coding:utf-8 -*-
"""
    # @Time:2022/12/9 0009 19:55
    # @Author:晚秋拾叶
    # @File:qt04_drawText.py
    # @PyCharm之Python
"""
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QPainter, QColor, QFont
from PyQt5.QtCore import Qt


class Drawing(QWidget):
    def __init__(self, parent=None):
        super(Drawing, self).__init__(parent)
        
        self.setWindowTitle("在窗口中绘制文字")
        self.resize(750, 200)
        self.text = "愚钝半生无羁客,飘零晚秋拾落叶"

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.begin(self)
        # 自定义绘制方法
        self.drawText(event, painter)
        painter.end()

    def drawText(self, event, qp):
        # 设置画笔的颜色
        qp.setPen(QColor(168, 34, 3))
        # 设置字体
        qp.setFont(QFont('SimSun', 20))
        # 绘制文字
        qp.drawText(event.rect(), Qt.AlignCenter, self.text)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Drawing()
    win.show()
    sys.exit(app.exec_())

  • 代码分析
    • 首先定义要绘制的文字(其实是有屏幕上的一个个点point组成的),然后定义绘制事件,所有的绘制操作都发生在此事件内。代码如下
      def paintEvent(self, event):
           painter = QPainter(self)
           painter.begin(self)
           # 调用自定义绘制方法
           self.drawText(event, painter)
           painter.end()
      
    • QtGui.QPainter类负责所有低级别的绘制,所有的绘制方法都要放在begin()和end()之间。
    • 下面是自定义的drawText()方法
      def drawText(self, event, qp):
      	# 设置笔的颜色
      	qp.setPen(QColor(168, 34, 3))
      	# 设置字体
      	qp.setFont(QFont('simSun', 20)
      	# 绘制文字
      	qp.drawText(event.rect(), Qt.AlignCenter, self.text)
      
  • 效果如图 在这里插入图片描述

案例二十六 绘制点

# -*- coding:utf-8 -*-
"""
    # @Time:2022/12/9 0009 21:07
    # @Author:晚秋拾叶
    # @File:qt04_drawPoint.py
    # @PyCharm之Python
"""
import math
import sys

from PyQt5.QtCore import Qt
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class Drawing(QWidget):
    def __init__(self, parent=None):
        super(Drawing, self).__init__(parent)
        self.setWindowTitle("在窗口中绘制点")
        self.resize(400, 200)

    def paintEvent(self, event):
        # 初始化绘图工具
        qp = QPainter()
        # 开始在窗口中绘制
        qp.begin(self)
        # 自定义画点方法
        self.drawPoint(qp)
        # 结束在窗口中的绘制
        qp.end()

    def drawPoint(self, qp):
        # 设置笔的颜色
        qp.setPen(Qt.red)
        # 获取当前窗口大小
        size = self.size()

        for i in range(1000):
            # 绘制正弦函数图形,它的周期是[-100, 100]
            x = 100 *(-1 + 2.0 * i / 1000) + size.width() / 2.0
            y = -50 * math.sin((x - size.width() / 2.0) * math.pi / 50) + size.height() / 2.0

            # 因为下面代码运行出现闪退,所以把(x, y)进行了int处理
            # qp.drawPoint(x, y)
            qp.drawPoint(int(x), int(y))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Drawing()
    win.show()
    sys.exit(app.exec_())
  • 代码分析
  • 在这个例子中,在窗口的工作区绘制正弦函数图形,周期是-100到100
  • 画笔是红色qp.setPen(Qt.red)
  • 每次调整窗口大小时,都会生成一个绘图事件。使用size()方法得到窗口的当前大小,在新的窗口中随机分布工作区中的点。
    size = self.size()
    
  • 使用drawPoint()方法绘制一个个点。
    # 因为下面代码运行出现闪退,所以把(x, y)进行了int处理
    # qp.drawPoint(x, y)
    qp.drawPoint(int(x), int(y))
    
  • 效果如图 在这里插入图片描述

2、QPen

  • QPen(钢笔)是一个基本的图形对象,用于绘制直线、曲线或者给轮廓画出矩形、椭圆形、多边形及其他形状等

案例二十七 QPen的使用

# -*- coding:utf-8 -*-
"""
    # @Time:2022/12/9 0009 22:43
    # @Author:晚秋拾叶
    # @File:qt04_drawPen.py
    # @PyCharm之Python
"""
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt


class Drawing(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 280, 270)
        self.setWindowTitle("钢笔样式案例")

    def paintEvent(self, e):
        qp = QPainter()
        qp.begin(self)
        self.drawLines(qp)
        qp.end()

    def drawLines(self, qp):

        # 定义一个笔,并设置黑色、宽度2像素、SolidLine样式
        pen = QPen(Qt.black, 2, Qt.SolidLine)

        # 给函数传参
        qp.setPen(pen)
        qp.drawLine(20, 40, 250, 40)

        pen.setStyle(Qt.DashLine)
        qp.setPen(pen)
        qp.drawLine(20, 80, 250, 80)

        pen.setStyle(Qt.DashDotLine)
        qp.setPen(pen)
        qp.drawLine(20, 120, 250, 120)

        pen.setStyle(Qt.DotLine)
        qp.setPen(pen)
        qp.drawLine(20, 160, 250, 160)

        pen.setStyle(Qt.DashDotDotLine)
        qp.setPen(pen)
        qp.drawLine(20, 200, 250, 200)

        # 这是自定义的线条样式
        pen.setStyle(Qt.CustomDashLine)
        pen.setDashPattern([1, 4, 5, 4])
        qp.setPen(pen)
        qp.drawLine(20, 240, 250, 240)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Drawing()
    win.show()
    sys.exit(app.exec_())

    
  • 代码分析
    • 在这个例子中,使用6种不同的线条样式绘制了6条线,其中前5条线使用的是预定义的线条样式。也可以自定义线条样式,最后一条线就是使用自定义的线条样式绘制的。
    • 程序代码创建了一个QPen对象。为了能更清晰地看清各线之间的差异,将颜色设置成黑色,宽度设置为2像素(px)。Qt.SolidLine是预定义的线条样式之一。
      pen = QPen(Qt.black, 2, Qt.solidLine)
      
    • 以下代码自定义了一种线条样式。使用Qt.CustomDashLine创建线条样式,然后调用setDashPattern()方法使用数字列表定义样式。数字列表的个数必须是偶数,在本例中数字列表是[1,4,5,4],它的个数是4。在数字列表中,奇数位(数字列表中的第1,3,5等位置)代表一段横线,偶数位(数字列表中的第2,4,6等位置)代表两段横线之间的空余距离。在数字列表中数字越大,横线和空余距离就越大。本例中数字列表[1,4,5,4]代表的意义是:1像素宽度的横线,4像素宽度在空余距离,5像素宽度的横线,4像素宽度的空余距离。
      pen.setStyle(Qt.CustomDashLine)
      pen.setDashPattern([1,4,5,4])
      qp.setPen(pen)
      qp.drawLine(20, 240, 250, 240)
      
  • 效果如图 在这里插入图片描述

3、QBrush

  • QBrush(画刷)是一个基本的图形对象,用于填充如矩形、椭圆形或多边形等形状。QBrush有三种类型:预定义、过渡和纹理图案。

案例二十八 QBrush的使用

# -*- coding:utf-8 -*-
"""
    # @Time:2022/12/10 0010 0:05
    # @Author:晚秋拾叶
    # @File:qt04_drawBrush.py
    # @PyCharm之Python

    【简介】
    绘图中QBrush 的例子 ,绘制九个不同样式的矩形。
"""

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt


class Drawing(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 365, 280)
        self.setWindowTitle('画刷案例')
        self.show()

    def paintEvent(self, e):
        qp = QPainter()
        qp.begin(self)
        self.drawLines(qp)
        qp.end()

    def drawLines(self, qp):
        brush = QBrush(Qt.SolidPattern)
        qp.setBrush(brush)
        qp.drawRect(10, 15, 90, 60)

        brush = QBrush(Qt.Dense1Pattern)
        qp.setBrush(brush)
        qp.drawRect(130, 15, 90, 60)

        brush = QBrush(Qt.Dense2Pattern)
        qp.setBrush(brush)
        qp.drawRect(250, 15, 90, 60)

        brush = QBrush(Qt.Dense3Pattern)
        qp.setBrush(brush)
        qp.drawRect(10, 105, 90, 60)

        brush = QBrush(Qt.DiagCrossPattern)
        qp.setBrush(brush)
        qp.drawRect(10, 105, 90, 60)

        brush = QBrush(Qt.Dense5Pattern)
        qp.setBrush(brush)
        qp.drawRect(130, 105, 90, 60)

        brush = QBrush(Qt.Dense6Pattern)
        qp.setBrush(brush)
        qp.drawRect(250, 105, 90, 60)

        brush = QBrush(Qt.HorPattern)
        qp.setBrush(brush)
        qp.drawRect(10, 195, 90, 60)

        brush = QBrush(Qt.VerPattern)
        qp.setBrush(brush)
        qp.drawRect(130, 195, 90, 60)

        brush = QBrush(Qt.BDiagPattern)
        qp.setBrush(brush)
        qp.drawRect(250, 195, 90, 60)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Drawing()
    win.show()
    sys.exit(app.exec_())

  • 代码分析

    • 在这个例子中,在窗口中绘制出9种不同背景填充的矩形。

    • 以下代码定义了QBrush对象,然后将QPainter对象的画刷设置成QBrush对象,并通过调用drawRect()方法绘制矩形。

      brush = QBrush(Qt.SolidPattern)
      qp.setBrush(brush)
      qp.drawRect(10, 15, 90, 60)
      
  • 效果如图 在这里插入图片描述

4、QPixmap

  • QPixmap类用于绘图设备的图像显示,它可以作为一个QPaintDevice对象,也可以加载到一个控件中,通常是标签或按钮,用于在标签或按钮上显示图像。 QPixmap可以读取的图像文件类型有BMP、GIF、JPG、JPEG、PNG、PBM、PGM、PPM、XBM 、XPM等。

  • QPixmap类中常用方法

方法 描述
copy() 从 QRect对象复制到QPixmap对象
fromImage() 将 Qlmage对象转换为QPixmap对象
grabWidget() 从给定的窗口小控件创建一个像素图
grabWindow() 在窗口中创建数据的像素图
load() 加载图像文件作为 QPixmap对象
save() 将QPixmap对象保存为文件
toImage() 将QPixmap对象转换为QImage对象

案例二十九 QPixmap的使用

# -*- coding:utf-8 -*-
"""
    # @Time:2022/12/10 0010 0:27
    # @Author:晚秋拾叶
    # @File:qt04_QPixmap.py
    # @PyCharm之Python
"""
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = QWidget()
    lab1 = QLabel()
    lab1.setPixmap(QPixmap("./images/child.jpg"))
    vbox = QVBoxLayout()
    vbox.addWidget(lab1)
    win.setLayout(vbox)
    win.setWindowTitle("QPixmap 例子")
    win.show()
    sys.exit(app.exec_())

  • 代码分析
    • 在这个例子中,使用setPixmap()将图像显示在QLabel上。

      lab1 = QLabel()
      lab1.setPixmap("./images/child.jpg"))
      
    • 上面的“./”代表程序运行目录(打开的目录)

  • 效果如图 在这里插入图片描述