[Qt扒手2] PyQt5 路径绘画例子

【说明】

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

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

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

本例基于: Win7 + Python 3.4 + PyQt5

【效果图】

对比原C++界面:

【源代码】

  1 # File: Painter Paths Example.py
  2 # Author: Robin
  3 # Date: 2015.2.9
  4 # C++: http://doc.qt.io/qt-5/qtwidgets-painting-painterpaths-example.html
  5
  6 import math
  7 from PyQt5.QtCore import *
  8 from PyQt5.QtGui import *
  9 from PyQt5.QtWidgets import *
 10
 11
 12 class RenderArea(QWidget):
 13     def __init__(self, path, parent=None):
 14         super(RenderArea, self).__init__(parent)
 15         self.penWidth = 1
 16         self.rotationAngle = 0
 17         self.path = path
 18         self.setBackgroundRole(QPalette.Base)
 19         self.setAutoFillBackground(True)
 20
 21     def minimumSizeHint(self):
 22         return QSize(50, 50)
 23
 24     def sizeHint(self):
 25         return QSize(100, 100)
 26
 27     def setFillRule(self, rule):
 28         self.path.setFillRule(rule)
 29         self.update()
 30
 31     def setFillGradient(self, color1, color2):
 32         self.fillColor1 = color1
 33         self.fillColor2 = color2
 34         self.update()
 35
 36     def setPenWidth(self, width):
 37         self.penWidth = width
 38         self.update()
 39
 40     def setPenColor(self, color):
 41         self.penColor = color
 42         self.update()
 43
 44     def setRotationAngle(self, degrees):
 45         self.rotationAngle = degrees
 46         self.update()
 47
 48     def paintEvent(self, event):
 49         painter = QPainter(self)
 50         painter.setRenderHint(QPainter.Antialiasing)
 51         painter.scale(self.width() / 100.0, self.height() / 100.0)
 52         painter.translate(50.0, 50.0)
 53         painter.rotate(-self.rotationAngle)
 54         painter.translate(-50.0, -50.0)
 55         painter.setPen(QPen(self.penColor, self.penWidth, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
 56         gradient = QLinearGradient(0, 0, 0, 100)
 57         gradient.setColorAt(0.0, self.fillColor1)
 58         gradient.setColorAt(1.0, self.fillColor2)
 59         painter.setBrush(gradient)
 60         painter.drawPath(self.path)
 61
 62
 63 class MyWindow(QWidget):
 64
 65     def __init__(self):
 66         super(MyWindow, self).__init__()
 67         #self.setUi()
 68         #self.Pi = 3.1415926
 69         # 矩形路径
 70         self.rectPath = QPainterPath()
 71         self.rectPath.moveTo(20.0, 30.0)
 72         self.rectPath.lineTo(80.0, 30.0)
 73         self.rectPath.lineTo(80.0, 70.0)
 74         self.rectPath.lineTo(20.0, 70.0)
 75         self.rectPath.closeSubpath()
 76         # 圆角矩形路径
 77         self.roundRectPath = QPainterPath()
 78         self.roundRectPath.moveTo(80.0, 35.0)
 79         self.roundRectPath.arcTo(70.0, 30.0, 10.0, 10.0, 0.0, 90.0)
 80         self.roundRectPath.lineTo(25.0, 30.0)
 81         self.roundRectPath.arcTo(20.0, 30.0, 10.0, 10.0, 90.0, 90.0)
 82         self.roundRectPath.lineTo(20.0, 65.0)
 83         self.roundRectPath.arcTo(20.0, 60.0, 10.0, 10.0, 180.0, 90.0)
 84         self.roundRectPath.lineTo(75.0, 70.0)
 85         self.roundRectPath.arcTo(70.0, 60.0, 10.0, 10.0, 270.0, 90.0)
 86         self.roundRectPath.closeSubpath()
 87         # 椭圆路径
 88         self.ellipsePath = QPainterPath()
 89         self.ellipsePath.moveTo(80.0, 50.0)
 90         self.ellipsePath.arcTo(20.0, 30.0, 60.0, 40.0, 0.0, 360.0)
 91         # 饼图路径
 92         self.piePath = QPainterPath()
 93         self.piePath.moveTo(50.0, 50.0)
 94         self.piePath.arcTo(20.0, 30.0, 60.0, 40.0, 60.0, 240.0)
 95         self.piePath.closeSubpath()
 96         # 多边形路径
 97         self.polygonPath = QPainterPath()
 98         self.polygonPath.moveTo(10.0, 80.0)
 99         self.polygonPath.lineTo(20.0, 10.0)
100         self.polygonPath.lineTo(80.0, 30.0)
101         self.polygonPath.lineTo(90.0, 70.0)
102         self.polygonPath.closeSubpath()
103         # 组合路径
104         self.groupPath = QPainterPath()
105         self.groupPath.moveTo(60.0, 40.0)
106         self.groupPath.arcTo(20.0, 20.0, 40.0, 40.0, 0.0, 360.0)
107         self.groupPath.moveTo(40.0, 40.0)
108         self.groupPath.lineTo(40.0, 80.0)
109         self.groupPath.lineTo(80.0, 80.0)
110         self.groupPath.lineTo(80.0, 40.0)
111         self.groupPath.closeSubpath()
112         # 文字路径
113         self.textPath = QPainterPath()
114         self.timesFont = QFont("Times", 50)
115         self.timesFont.setStyleStrategy(QFont.ForceOutline)
116         self.textPath.addText(10, 70, self.timesFont, "Qt")
117         # 贝兹尔路径
118         self.bezierPath = QPainterPath()
119         self.bezierPath.moveTo(20, 30)
120         self.bezierPath.cubicTo(80, 0, 50, 50, 80, 80)
121
122         self.starPath = QPainterPath()
123         self.starPath.moveTo(90, 50)
124         for i in range(5):
125             self.starPath.lineTo(50 + 40 * math.cos(0.8 * i * math.pi),
126                             50 + 40 * math.sin(0.8 * i * math.pi))
127         self.starPath.closeSubpath()
128
129         self.renderAreas = []
130         self.renderAreas.append(RenderArea(self.rectPath))
131         self.renderAreas.append(RenderArea(self.roundRectPath))
132         self.renderAreas.append(RenderArea(self.ellipsePath))
133         self.renderAreas.append(RenderArea(self.piePath))
134         self.renderAreas.append(RenderArea(self.polygonPath))
135         self.renderAreas.append(RenderArea(self.groupPath))
136         self.renderAreas.append(RenderArea(self.textPath))
137         self.renderAreas.append(RenderArea(self.bezierPath))
138         self.renderAreas.append(RenderArea(self.starPath))
139
140     #def setUi(self):
141         self.fillRuleComboBox = QComboBox()
142         self.fillRuleComboBox.addItem("Odd Even", Qt.OddEvenFill)
143         self.fillRuleComboBox.addItem("Winding", Qt.WindingFill)
144
145         self.fillRuleLabel = QLabel("Fill &Rule:")
146         self.fillRuleLabel.setBuddy(self.fillRuleComboBox)
147
148         self.fillColor1ComboBox = QComboBox()
149         self.populateWithColors(self.fillColor1ComboBox)
150         self.fillColor1ComboBox.setCurrentIndex(self.fillColor1ComboBox.findText("mediumslateblue"))
151
152         self.fillColor2ComboBox = QComboBox()
153         self.populateWithColors(self.fillColor2ComboBox)
154         self.fillColor2ComboBox.setCurrentIndex(self.fillColor2ComboBox.findText("cornsilk"))
155
156         self.fillGradientLabel = QLabel("&Fill Gradient:")
157         self.fillGradientLabel.setBuddy(self.fillColor1ComboBox)
158
159         self.fillToLabel = QLabel("to")
160         self.fillToLabel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
161
162         self.penWidthSpinBox = QSpinBox()
163         self.penWidthSpinBox.setRange(0, 20)
164
165         self.penWidthLabel = QLabel("&Pen Width:")
166         self.penWidthLabel.setBuddy(self.penWidthSpinBox)
167
168         self.penColorComboBox = QComboBox()
169         self.populateWithColors(self.penColorComboBox)
170         self.penColorComboBox.setCurrentIndex(self.penColorComboBox.findText("darkslateblue"))
171
172         self.penColorLabel = QLabel("Pen &Color:")
173         self.penColorLabel.setBuddy(self.penColorComboBox)
174
175         self.rotationAngleSpinBox = QSpinBox()
176         self.rotationAngleSpinBox.setRange(0, 359)
177         self.rotationAngleSpinBox.setWrapping(True)
178         self.rotationAngleSpinBox.setSuffix("°")
179
180         self.rotationAngleLabel = QLabel("&Rotation Angle:")
181         self.rotationAngleLabel.setBuddy(self.rotationAngleSpinBox)
182
183         self.fillRuleComboBox.activated.connect(self.fillRuleChanged)
184         self.fillColor1ComboBox.activated.connect(self.fillGradientChanged)
185         self.fillColor2ComboBox.activated.connect(self.fillGradientChanged)
186         self.penColorComboBox.activated.connect(self.penColorChanged)
187
188         for it in self.renderAreas:
189             self.penWidthSpinBox.valueChanged.connect(it.setPenWidth)
190             self.rotationAngleSpinBox.valueChanged.connect(it.setRotationAngle)
191
192
193         topLayout = QGridLayout()
194
195         i = 0
196         for i, it in enumerate(self.renderAreas):
197             topLayout.addWidget(it, i // 3, i % 3)
198
199
200         mainLayout = QGridLayout()
201         mainLayout.addLayout(topLayout, 0, 0, 1, 4)
202         mainLayout.addWidget(self.fillRuleLabel, 1, 0)
203         mainLayout.addWidget(self.fillRuleComboBox, 1, 1, 1, 3)
204         mainLayout.addWidget(self.fillGradientLabel, 2, 0)
205         mainLayout.addWidget(self.fillColor1ComboBox, 2, 1)
206         mainLayout.addWidget(self.fillToLabel, 2, 2)
207         mainLayout.addWidget(self.fillColor2ComboBox, 2, 3)
208         mainLayout.addWidget(self.penWidthLabel, 3, 0)
209         mainLayout.addWidget(self.penWidthSpinBox, 3, 1, 1, 3)
210         mainLayout.addWidget(self.penColorLabel, 4, 0)
211         mainLayout.addWidget(self.penColorComboBox, 4, 1, 1, 3)
212         mainLayout.addWidget(self.rotationAngleLabel, 5, 0)
213         mainLayout.addWidget(self.rotationAngleSpinBox, 5, 1, 1, 3)
214         self.setLayout(mainLayout)
215
216         self.fillRuleChanged()
217         self.fillGradientChanged()
218         self.penColorChanged()
219         self.penWidthSpinBox.setValue(2)
220
221         self.setWindowTitle("Painter Paths")
222
223     def fillRuleChanged(self):
224         rule = self.currentItemData(self.fillRuleComboBox)
225         for it in self.renderAreas:
226             it.setFillRule(rule)
227
228     def fillGradientChanged(self):
229         color1 = self.currentItemData(self.fillColor1ComboBox)
230         color2 = self.currentItemData(self.fillColor2ComboBox)
231         for it in self.renderAreas:
232             it.setFillGradient(color1, color2)
233
234     def penColorChanged(self):
235         color = self.currentItemData(self.penColorComboBox)
236         for it in self.renderAreas:
237             it.setPenColor(color)
238
239     @staticmethod
240     def populateWithColors(comboBox):
241         colorNames = QColor.colorNames()
242         for name in colorNames:
243             comboBox.addItem(name, QColor(name))
244
245     @staticmethod
246     def currentItemData(comboBox):
247         return comboBox.itemData(comboBox.currentIndex(),Qt.UserRole)
248
249
250 if __name__ == "__main__":
251     import sys
252     app = QApplication(sys.argv)
253     win = MyWindow()
254     win.show()
255     sys.exit(app.exec_())

时间: 2024-08-29 08:22:21

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

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

[说明] 好吧,坦白从宽,我是Qt扒手(不要鄙视我).这是我根据qt官网提供的C++版本的例子(http://doc.qt.io/qt-5/qtwidgets-painting-basicdrawing-example.html),改编而成的Python版本. 由于本人没有C++基础,其难度之大,自不待言. 不过,还是毛主席说的好:道路是艰难的,结果是光明的:) 本文基于 win7 + Python3.4 + PyQt5  环境 [效果图] 对比原C++的界面: [源代码] 1 # File:

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

在网上直接下载别人编译好的Qt库,为自己使用省了不少事.但往往也会遇到些问题,其中Qt version is not properly installed,please run make installQt没有被正确安装,请运行make install这个问题是比较常见的一个.网上看了一个帖子,终于明白原因所在,原来是qmake.exe是在Qt安装编译时生成的,里面内嵌了Qt相关的一些路径.如果直接拷贝过来使用,自己的路径结构与原来不同,则Qt库就不能正常使用.提示就是Qt version is

自定义View时,用到Paint Canvas的一些温故,讲讲用路径绘画实现动画效果(基础篇 三)

转载请注明出处王亟亟的大牛之路 上礼拜上了一篇关于动画的自定义View的文章,然后里面的实现是PathMeasure,然后这一部分貌似以前没有讲过,那么就再补一篇来介绍下这部分的知识(之前一篇的传送门:http://blog.csdn.net/ddwhan0123/article/details/51066859) 直接说有点抽象,我们来看下演示的效果: 动的时候,是这样子 那暂停是这样子 其实这样的实现,一个个坐标增量画然后一直Invalidate也能做,但是写起来太麻烦,PathMeasur

Qt中将编译输出路径设置在其他文件

在进行Qt程序编译的时候,经常用Qtcreator来搞定,在这上面当然简单了,完全的图形界面操作,然后还可以设置编译输出的路径.然而由于项目需要,当把程序放到嵌入式上运行时就不能这么做了,因为很多嵌入式平台没有那么多资源,只能在命令行里qmake和make了,但是这里会出现一个问题,就是单纯地在项目目录下qmake和make会使得所有编译出来的文件全部堆在项目目录下,这样就会使项目的管理比较混乱,这里使用了两种方法可以使得编译的文件不会出现在项目文件下. 第一种是给qmake和make加一点参数

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

转自:http://my.oschina.net/voler/blog/345722 目录[-] 0. 源代码下载地址 1. 简单文件拖放 2. 复杂文件拖放 3. 通过按钮来完成列表数据的转移 4. 通过拖放文件来达到效果 1. 简单文件拖放 1. 一般情况下,编辑框可以直接接收到文件名 2. 程序效果图 2. 复杂文件拖放 1. 关键代码如下 2. 程序效果图 3. 通过按钮来完成列表数据的转移 1. 关键代码 2. 程序效果图 4. 通过拖放文件来达到效果 1. 关键代码 2. 效果图(通

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

Contents Style Sheet Usage Customizing the Foreground and Background Colors Customizing Using Dynamic Properties Customizing a QPushButton Using the Box Model Customizing the QPushButton's Menu Indicator Sub-Control Complex Selector Example Customizi

QT和JS的互相调用例子

转自: http://blog.163.com/[email protected]/blog/static/15822093201682185819623/ Qt 4.8.4 感谢原作者,我只转载. 看看作者如何实现: 1.Qt源码调用html中js的函数disp_messagebox(): 2.js源码中如何调用qt中的函数   MainWindow.jsInvokeQt(); MainWindow.setInfor("Qt change string"); alert(MainWi

相对路径与绝对路径特殊例子解析

概念: 相对路径:从当前目录开始引起的与其它路径相关关系(不固定). 绝对路径:带域名的完整路径(固定). 示例: 相对路径:  ./ 代表的是源文件当前文件夹路径 如图:index.html要链接index.css路径(这是一个错误的示例) 链接后的路径: 绝对路径:  / 代表的是项目根路径 如图:index.html要链接index.css路径(这是一个错误的示例) 链接后的路径:

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

QList<QString> qlist = path.split(QRegExp("[\\\\/]")); QString FileName = qlist.at(qlist.size()-1); //截取路径中最后一段