【说明】

此例扒自 Qt 官网,原例是 C++ 代码,我把它改写成了 Python + PyQt5 版本。

有了前一个例子的成功,这个例子改写的非常之快。记得第一个例子花了我几天的时间,而这个例子只花了半个小时。

当然,过程中也遇到了一些新问题,比如 renderAreas 被定义成 QList类,而QList类的迭代,调试了几次都报错。没有办法,干脆把renderAreas 修改定义为Python的 list 类型,然后就OK了!!

本例基于: Win7 + Python 3.4 + PyQt5

【效果图】

对比原C++界面:

【源代码】

 # 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_())

[Qt扒手2] PyQt5 路径绘画例子的更多相关文章

  1. [Qt扒手] PyQt5 基础绘画例子

    [说明] 好吧,坦白从宽,我是Qt扒手(不要鄙视我).这是我根据qt官网提供的C++版本的例子(http://doc.qt.io/qt-5/qtwidgets-painting-basicdrawin ...

  2. 基于Qt Designer和PyQt5的桌面软件开发--环境搭建和入门例子

      本文介绍了如何使用技术栈PyCharm+Qt Designer+PyQt5来开发桌面软件,从环境搭建.例子演示到对容易混淆概念的解释.文中用到的全部软件+代码下载链接为:https://url39 ...

  3. qmake.exe是在Qt安装编译时生成的,里面内嵌了Qt相关的一些路径(最简单的方法是保持一样的安装路径,最方便的办法是设置qt.conf文件)

    在网上直接下载别人编译好的Qt库,为自己使用省了不少事.但往往也会遇到些问题,其中Qt version is not properly installed,please run make instal ...

  4. QT应用程序 安装路径中文异常问题

    [1]QT 安装中文路径启动异常问题 最近在搞一个很简单的QT应用程序,开发环境VS2017 + QT5.9,线上异常报错:安装中文路径下启动崩溃~~~~ 最后,本地调试Debug版本,发现安装中文路 ...

  5. Qt内的各种路径(让人迷惑)

    Qt里面各种获取程序路径或者当前路径的写法,在此梳理一下,以防今后开发的程序中路径不统一 1.利用QDir获取路径 QDir::currentPath() 此路径是项目编译生成的路径即可执行文件所在目 ...

  6. 【QT】利用pyqt5实现简单界面

    Topic: 利用pyqt5编写简单界面Env:win10 + Pycharm2018 + Python 3.6.8Date: 2019/4/29 by hw_Chen2018            ...

  7. qt 3 获取文件路径中的一部分

    QList<QString> qlist = path.split(QRegExp("[\\\\/]")); QString FileName = qlist.at(q ...

  8. Qt Style Sheets Examples(官方例子目录,很全)

    Contents Style Sheet Usage Customizing the Foreground and Background Colors Customizing Using Dynami ...

  9. QT实现拖放文件(有例子,并且图文并茂,非常清楚)

    转自:http://my.oschina.net/voler/blog/345722 目录[-] 0. 源代码下载地址 1. 简单文件拖放 2. 复杂文件拖放 3. 通过按钮来完成列表数据的转移 4. ...

随机推荐

  1. 标准的Flask启动文件

    最近有一些同学问了我一些项目结构的问题 所以今天给大家专门讲解 解耦后的项目 目录我会分为两种方式:一种是普通解耦 一种是多mvc解耦 首先 我没先建立我们程序的文件夹并且在这个文件夹内写一个和这个文 ...

  2. Oracle数据库运维:要对监听日志文件(listener.log)进行定期清理,如果不定期清理,会遇到下面一些麻烦

    原文链接: http://www.lookdaima.com/WebForms/WebPages/Blanks/Pm/Docs/DocItemDetail.aspx?EmPreviewTypeV=2& ...

  3. September 24th 2017 Week 39th Sunday

    To live is the rarest thing in the world. Most people exist. That is all. 生活是世间最罕见的事情:生存,却是世间最常见的事情: ...

  4. hadoop学习;hdfs操作;执行抛出权限异常: Permission denied;api查看源代码方法;源代码不停的向里循环;抽象类通过debug查找源代码

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u010026901/article/details/26587251 eclipse快捷键alt+s ...

  5. [SDOI2017]切树游戏

    题目 二轮毒瘤题啊 辣鸡洛谷竟然有卡树剖的数据 还是\(loj\)可爱 首先这道题没有带修,设\(dp_{i,j}\)表示以\(i\)为最高点的连通块有多少个异或和为\(j\),\(g_{i,j}=\ ...

  6. java基础面试题(JVM篇)

    1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程.Java 源文件被编译成能被 Java 虚拟机执行的字节码文件. ...

  7. mysql 二进制日志binary log操作简单命令

    show master status \G; #查看当前正在记录的二进制日志 show binary logs; #查看binary log 所有文件列表 show binlog events; #查 ...

  8. 【LeetCode67】 Add Binary

    题目描述: 解题思路: 此题的思路简单,下面的代码用StringBuilder更加简单,注意最后的结果要反转过来.[LeetCode415]Add Strings的解法和本题一模一样. java代码: ...

  9. Object C学习笔记12-集合

    这里讲到的集合是指Set集合,其实Array也是一种类型的集合.在Object C中提供了两个集合类NSSet和NSMutableSet.其实NSSet和NSArray性质一样,都是用于存储对象的. ...

  10. MySQL基础----py全栈

    目录 MySQL基础----py全栈 一.引言 1.什么是数据? 2.什么是数据库(DB)? 3.什么是数据库管理系统(DBMS)? 4.什么是数据库系统? 5.数据库管理系统由来 6.什么是数据模型 ...