如何通过 using\combining 多种形状在 Qt 中绘制自定义形状
How to draw custom shape in Qt by using\combining many shapes
如何使用(组合)其他基本形状(圆和线)绘制自定义形状?
我的问题是,如果我想旋转那个自定义形状,我需要做一些数学运算并旋转所有其他基本形状并重新定位。如何避免这种情况,在一个参数中我可以旋转整个自定义形状。
我想要这样的东西(例如):
orientation_angale = 40 # i.e
custom_shape.rotate(orientation_angale)
绘制上图的代码如下:
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import QPoint, QPointF
class CustomShape(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.pixmap = QtGui.QPixmap()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(self.rect(), self.pixmap)
pen = QtGui.QPen()
pen.setWidth(1)
painter.setPen(pen)
# =========== Draw big circle ===========
x, y = 100, 100
r = 150
painter.drawEllipse(x, y, r, r)
# =========== Draw top line ===========
s_point_x = x + r / 2 # centre of the big circle
s_point_y = y
s_point = QPointF(s_point_x, s_point_y)
e_point_x = x + r / 2 # centre of the big circle
e_point_y = y - 20
e_point = QPointF(e_point_x, e_point_y)
painter.drawLine(s_point, e_point)
# =========== Draw small circle ===========
s_r = 10
s_x, s_y = x + (r / 2) - (s_r / 2), e_point_y - s_r
painter.drawEllipse(s_x, s_y, s_r, s_r)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = CustomShape()
w.resize(400, 400)
w.show()
sys.exit(app.exec_())
这是默认方向:
我想旋转那个自定义形状,所以它应该看起来像这样(旋转将应用 360 度)
您可以使用painter.rotate()
函数,但请记住旋转始终围绕原点(0, 0
),因此您首先必须translate到旋转中心,然后旋转,平移回来。
考虑一下您可以使用 QPainterPath 在单个元素中“存储”高级形状(另一种方法是使用 QPicture,它允许“缓存”QPainter 操作)。
class CustomShape(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.pixmap = QtGui.QPixmap()
self.setMinimumSize(210, 210)
self.path = QtGui.QPainterPath()
self.path.addEllipse(100, 100, 150, 150)
self.path.moveTo(175, 100)
self.path.lineTo(175, 80)
self.path.addEllipse(170, 70, 10, 10)
self.center = QtCore.QPoint(175, 175)
self.angle = 0
def setAngle(self, angle):
self.angle = angle % 360
self.update()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(self.rect(), self.pixmap)
painter.setRenderHint(painter.Antialiasing)
painter.translate(self.center)
painter.rotate(self.angle)
painter.translate(-self.center)
painter.drawPath(self.path)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = CustomShape()
w.resize(400, 400)
timer = QtCore.QTimer(interval=100)
timer.timeout.connect(lambda: w.setAngle(w.angle + 1))
timer.start()
w.show()
sys.exit(app.exec_())
请注意,Qt 提供了可用于计算简单几何图形和位置的辅助函数;虽然并不总是适合频繁更新,但由于它依赖于 C++ 函数,因此它 通常 比计算 python 方面的所有内容更快,或者至少,它提供了更好的可读形式:
class CustomShape(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.pixmap = QtGui.QPixmap()
self.setMinimumSize(210, 210)
self.center = QtCore.QPoint(175, 175)
self.bigRadius = 75
self.smallRadius = 5
self.distance = 20
self.angle = 0
def setAngle(self, angle):
self.angle = angle % 360
self.update()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(self.rect(), self.pixmap)
painter.setRenderHint(painter.Antialiasing)
painter.drawEllipse(self.center, self.bigRadius, self.bigRadius)
fullExtent = self.bigRadius + self.distance
# create a line that extents to the edge of the small circle
line = QtCore.QLineF.fromPolar(fullExtent, 90 - self.angle)
# translate it to the center
line.translate(self.center)
# move the origin point based on the ratio of the radius
line.setP1(line.pointAt(self.bigRadius / fullExtent))
painter.drawLine(line)
# create a line similar to the above to get the center of the
# small circle
otherLine = QtCore.QLineF.fromPolar(
fullExtent + self.smallRadius, 90 - self.angle)
otherLine.translate(self.center)
painter.drawEllipse(otherLine.p2(), self.smallRadius, self.smallRadius)
如何使用(组合)其他基本形状(圆和线)绘制自定义形状?
我的问题是,如果我想旋转那个自定义形状,我需要做一些数学运算并旋转所有其他基本形状并重新定位。如何避免这种情况,在一个参数中我可以旋转整个自定义形状。
我想要这样的东西(例如):
orientation_angale = 40 # i.e
custom_shape.rotate(orientation_angale)
绘制上图的代码如下:
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import QPoint, QPointF
class CustomShape(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.pixmap = QtGui.QPixmap()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(self.rect(), self.pixmap)
pen = QtGui.QPen()
pen.setWidth(1)
painter.setPen(pen)
# =========== Draw big circle ===========
x, y = 100, 100
r = 150
painter.drawEllipse(x, y, r, r)
# =========== Draw top line ===========
s_point_x = x + r / 2 # centre of the big circle
s_point_y = y
s_point = QPointF(s_point_x, s_point_y)
e_point_x = x + r / 2 # centre of the big circle
e_point_y = y - 20
e_point = QPointF(e_point_x, e_point_y)
painter.drawLine(s_point, e_point)
# =========== Draw small circle ===========
s_r = 10
s_x, s_y = x + (r / 2) - (s_r / 2), e_point_y - s_r
painter.drawEllipse(s_x, s_y, s_r, s_r)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = CustomShape()
w.resize(400, 400)
w.show()
sys.exit(app.exec_())
这是默认方向:
我想旋转那个自定义形状,所以它应该看起来像这样(旋转将应用 360 度)
您可以使用painter.rotate()
函数,但请记住旋转始终围绕原点(0, 0
),因此您首先必须translate到旋转中心,然后旋转,平移回来。
考虑一下您可以使用 QPainterPath 在单个元素中“存储”高级形状(另一种方法是使用 QPicture,它允许“缓存”QPainter 操作)。
class CustomShape(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.pixmap = QtGui.QPixmap()
self.setMinimumSize(210, 210)
self.path = QtGui.QPainterPath()
self.path.addEllipse(100, 100, 150, 150)
self.path.moveTo(175, 100)
self.path.lineTo(175, 80)
self.path.addEllipse(170, 70, 10, 10)
self.center = QtCore.QPoint(175, 175)
self.angle = 0
def setAngle(self, angle):
self.angle = angle % 360
self.update()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(self.rect(), self.pixmap)
painter.setRenderHint(painter.Antialiasing)
painter.translate(self.center)
painter.rotate(self.angle)
painter.translate(-self.center)
painter.drawPath(self.path)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = CustomShape()
w.resize(400, 400)
timer = QtCore.QTimer(interval=100)
timer.timeout.connect(lambda: w.setAngle(w.angle + 1))
timer.start()
w.show()
sys.exit(app.exec_())
请注意,Qt 提供了可用于计算简单几何图形和位置的辅助函数;虽然并不总是适合频繁更新,但由于它依赖于 C++ 函数,因此它 通常 比计算 python 方面的所有内容更快,或者至少,它提供了更好的可读形式:
class CustomShape(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.pixmap = QtGui.QPixmap()
self.setMinimumSize(210, 210)
self.center = QtCore.QPoint(175, 175)
self.bigRadius = 75
self.smallRadius = 5
self.distance = 20
self.angle = 0
def setAngle(self, angle):
self.angle = angle % 360
self.update()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.drawPixmap(self.rect(), self.pixmap)
painter.setRenderHint(painter.Antialiasing)
painter.drawEllipse(self.center, self.bigRadius, self.bigRadius)
fullExtent = self.bigRadius + self.distance
# create a line that extents to the edge of the small circle
line = QtCore.QLineF.fromPolar(fullExtent, 90 - self.angle)
# translate it to the center
line.translate(self.center)
# move the origin point based on the ratio of the radius
line.setP1(line.pointAt(self.bigRadius / fullExtent))
painter.drawLine(line)
# create a line similar to the above to get the center of the
# small circle
otherLine = QtCore.QLineF.fromPolar(
fullExtent + self.smallRadius, 90 - self.angle)
otherLine.translate(self.center)
painter.drawEllipse(otherLine.p2(), self.smallRadius, self.smallRadius)