PyQt5利用QPainter绘制各种图形(转)-2

时间:2021-03-12 23:02:52


http://www.cnblogs.com/hhh5460/p/4281587.html


PyQt5利用QPainter绘制各种图形(转)-2


# File: Painter Paths Example.py
# Author: Robin
# Date: 2015.2.9
# C++: http://doc.qt.io/qt-5/qtwidgets-painting-painterpaths-example.html

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


class RenderArea(QWidget):
    def __init__(self, path, parent=None):
        super(RenderArea, self).__init__(parent)
        self.penWidth = 1
        self.rotationAngle = 0
        self.path = path
        self.setBackgroundRole(QPalette.Base)
        self.setAutoFillBackground(True)

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(100, 100)

    def setFillRule(self, rule):
        self.path.setFillRule(rule)
        self.update()

    def setFillGradient(self, color1, color2):
        self.fillColor1 = color1
        self.fillColor2 = color2
        self.update()

    def setPenWidth(self, width):
        self.penWidth = width
        self.update()

    def setPenColor(self, color):
        self.penColor = color
        self.update()

    def setRotationAngle(self, degrees):
        self.rotationAngle = degrees
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.scale(self.width() / 100.0, self.height() / 100.0)
        painter.translate(50.0, 50.0)
        painter.rotate(-self.rotationAngle)
        painter.translate(-50.0, -50.0)
        painter.setPen(QPen(self.penColor, self.penWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        gradient = QLinearGradient(0, 0, 0, 100)
        gradient.setColorAt(0.0, self.fillColor1)
        gradient.setColorAt(1.0, self.fillColor2)
        painter.setBrush(gradient)
        painter.drawPath(self.path)


class MyWindow(QWidget):

    def __init__(self):
        super(MyWindow, self).__init__()
        # self.setUi()
        # self.Pi = 3.1415926
        # 矩形路径
        self.rectPath = QPainterPath()
        self.rectPath.moveTo(20.0, 30.0)
        self.rectPath.lineTo(80.0, 30.0)
        self.rectPath.lineTo(80.0, 70.0)
        self.rectPath.lineTo(20.0, 70.0)
        self.rectPath.closeSubpath()
        # 圆角矩形路径
        self.roundRectPath = QPainterPath()
        self.roundRectPath.moveTo(80.0, 35.0)
        self.roundRectPath.arcTo(70.0, 30.0, 10.0, 10.0, 0.0, 90.0)
        self.roundRectPath.lineTo(25.0, 30.0)
        self.roundRectPath.arcTo(20.0, 30.0, 10.0, 10.0, 90.0, 90.0)
        self.roundRectPath.lineTo(20.0, 65.0)
        self.roundRectPath.arcTo(20.0, 60.0, 10.0, 10.0, 180.0, 90.0)
        self.roundRectPath.lineTo(75.0, 70.0)
        self.roundRectPath.arcTo(70.0, 60.0, 10.0, 10.0, 270.0, 90.0)
        self.roundRectPath.closeSubpath()
        # 椭圆路径
        self.ellipsePath = QPainterPath()
        self.ellipsePath.moveTo(80.0, 50.0)
        self.ellipsePath.arcTo(20.0, 30.0, 60.0, 40.0, 0.0, 360.0)
        # 饼图路径
        self.piePath = QPainterPath()
        self.piePath.moveTo(50.0, 50.0)
        self.piePath.arcTo(20.0, 30.0, 60.0, 40.0, 60.0, 240.0)
        self.piePath.closeSubpath()
        # 多边形路径
        self.polygonPath = QPainterPath()
        self.polygonPath.moveTo(10.0, 80.0)
        self.polygonPath.lineTo(20.0, 10.0)
        self.polygonPath.lineTo(80.0, 30.0)
        self.polygonPath.lineTo(90.0, 70.0)
        self.polygonPath.closeSubpath()
        # 组合路径
        self.groupPath = QPainterPath()
        self.groupPath.moveTo(60.0, 40.0)
        self.groupPath.arcTo(20.0, 20.0, 40.0, 40.0, 0.0, 360.0)
        self.groupPath.moveTo(40.0, 40.0)
        self.groupPath.lineTo(40.0, 80.0)
        self.groupPath.lineTo(80.0, 80.0)
        self.groupPath.lineTo(80.0, 40.0)
        self.groupPath.closeSubpath()
        # 文字路径
        self.textPath = QPainterPath()
        self.timesFont = QFont("Times", 50)
        self.timesFont.setStyleStrategy(QFont.ForceOutline)
        self.textPath.addText(10, 70, self.timesFont, "Qt")
        # 贝兹尔路径
        self.bezierPath = QPainterPath()
        self.bezierPath.moveTo(20, 30)
        self.bezierPath.cubicTo(80, 0, 50, 50, 80, 80)

        self.starPath = QPainterPath()
        self.starPath.moveTo(90, 50)
        for i in range(5):
            self.starPath.lineTo(50 + 40 * math.cos(0.8 * i * math.pi),
                                 50 + 40 * math.sin(0.8 * i * math.pi))
        self.starPath.closeSubpath()

        self.renderAreas = []
        self.renderAreas.append(RenderArea(self.rectPath))
        self.renderAreas.append(RenderArea(self.roundRectPath))
        self.renderAreas.append(RenderArea(self.ellipsePath))
        self.renderAreas.append(RenderArea(self.piePath))
        self.renderAreas.append(RenderArea(self.polygonPath))
        self.renderAreas.append(RenderArea(self.groupPath))
        self.renderAreas.append(RenderArea(self.textPath))
        self.renderAreas.append(RenderArea(self.bezierPath))
        self.renderAreas.append(RenderArea(self.starPath))

        # def setUi(self):
        self.fillRuleComboBox = QComboBox()
        self.fillRuleComboBox.addItem("Odd Even", Qt.OddEvenFill)
        self.fillRuleComboBox.addItem("Winding", Qt.WindingFill)

        self.fillRuleLabel = QLabel("Fill &Rule:")
        self.fillRuleLabel.setBuddy(self.fillRuleComboBox)

        self.fillColor1ComboBox = QComboBox()
        self.populateWithColors(self.fillColor1ComboBox)
        self.fillColor1ComboBox.setCurrentIndex(self.fillColor1ComboBox.findText("mediumslateblue"))

        self.fillColor2ComboBox = QComboBox()
        self.populateWithColors(self.fillColor2ComboBox)
        self.fillColor2ComboBox.setCurrentIndex(self.fillColor2ComboBox.findText("cornsilk"))

        self.fillGradientLabel = QLabel("&Fill Gradient:")
        self.fillGradientLabel.setBuddy(self.fillColor1ComboBox)

        self.fillToLabel = QLabel("to")
        self.fillToLabel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        self.penWidthSpinBox = QSpinBox()
        self.penWidthSpinBox.setRange(0, 20)

        self.penWidthLabel = QLabel("&Pen Width:")
        self.penWidthLabel.setBuddy(self.penWidthSpinBox)

        self.penColorComboBox = QComboBox()
        self.populateWithColors(self.penColorComboBox)
        self.penColorComboBox.setCurrentIndex(self.penColorComboBox.findText("darkslateblue"))

        self.penColorLabel = QLabel("Pen &Color:")
        self.penColorLabel.setBuddy(self.penColorComboBox)

        self.rotationAngleSpinBox = QSpinBox()
        self.rotationAngleSpinBox.setRange(0, 359)
        self.rotationAngleSpinBox.setWrapping(True)
        self.rotationAngleSpinBox.setSuffix("°")

        self.rotationAngleLabel = QLabel("&Rotation Angle:")
        self.rotationAngleLabel.setBuddy(self.rotationAngleSpinBox)

        self.fillRuleComboBox.activated.connect(self.fillRuleChanged)
        self.fillColor1ComboBox.activated.connect(self.fillGradientChanged)
        self.fillColor2ComboBox.activated.connect(self.fillGradientChanged)
        self.penColorComboBox.activated.connect(self.penColorChanged)

        for it in self.renderAreas:
            self.penWidthSpinBox.valueChanged.connect(it.setPenWidth)
            self.rotationAngleSpinBox.valueChanged.connect(it.setRotationAngle)

        topLayout = QGridLayout()

        i = 0
        for i, it in enumerate(self.renderAreas):
            topLayout.addWidget(it, i // 3, i % 3)

        mainLayout = QGridLayout()
        mainLayout.addLayout(topLayout, 0, 0, 1, 4)
        mainLayout.addWidget(self.fillRuleLabel, 1, 0)
        mainLayout.addWidget(self.fillRuleComboBox, 1, 1, 1, 3)
        mainLayout.addWidget(self.fillGradientLabel, 2, 0)
        mainLayout.addWidget(self.fillColor1ComboBox, 2, 1)
        mainLayout.addWidget(self.fillToLabel, 2, 2)
        mainLayout.addWidget(self.fillColor2ComboBox, 2, 3)
        mainLayout.addWidget(self.penWidthLabel, 3, 0)
        mainLayout.addWidget(self.penWidthSpinBox, 3, 1, 1, 3)
        mainLayout.addWidget(self.penColorLabel, 4, 0)
        mainLayout.addWidget(self.penColorComboBox, 4, 1, 1, 3)
        mainLayout.addWidget(self.rotationAngleLabel, 5, 0)
        mainLayout.addWidget(self.rotationAngleSpinBox, 5, 1, 1, 3)
        self.setLayout(mainLayout)

        self.fillRuleChanged()
        self.fillGradientChanged()
        self.penColorChanged()
        self.penWidthSpinBox.setValue(2)

        self.setWindowTitle("Painter Paths")

    def fillRuleChanged(self):
        rule = self.currentItemData(self.fillRuleComboBox)
        for it in self.renderAreas:
            it.setFillRule(rule)

    def fillGradientChanged(self):
        color1 = self.currentItemData(self.fillColor1ComboBox)
        color2 = self.currentItemData(self.fillColor2ComboBox)
        for it in self.renderAreas:
            it.setFillGradient(color1, color2)

    def penColorChanged(self):
        color = self.currentItemData(self.penColorComboBox)
        for it in self.renderAreas:
            it.setPenColor(color)

    @staticmethod
    def populateWithColors(comboBox):
        colorNames = QColor.colorNames()
        for name in colorNames:
            comboBox.addItem(name, QColor(name))

    @staticmethod
    def currentItemData(comboBox):
        return comboBox.itemData(comboBox.currentIndex(), Qt.UserRole)


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    win = MyWindow()
    win.show()
    sys.exit(app.exec_())