PyQt绘制对称分形树遇递归逻辑问题求助
PyQt 对称分形树递归问题解决办法
我看了你尝试用PyQt绘制对称分形树的两段代码,问题核心都出在递归时的画家状态管理上——没有正确恢复平移、旋转的状态,导致分支的位置偏移,破坏了树形的对称性。下面我帮你分析问题并给出修正后的代码:
原代码的问题分析
第一段代码的问题
在右分支的绘制逻辑中,你多添加了一行不必要的p.translate(0, len):
p.setTransform(self.transform) self.transform = p.transform() p.rotate(-self.angle) p.translate(0, len) # 这里是多余的! self.branch(p, len)
这个平移操作会让右分支的起点向下偏移,直接打破了左右分支的对称关系。
第二段代码的问题
递归调用后,旋转和平移的顺序混乱,且没有正确恢复画家的初始状态。每次递归修改的画家状态会影响后续分支,导致树形逐渐偏移,无法保持对称。
修正后的代码
解决这个问题的关键是利用QPainter的save()和restore()方法来管理状态——每次递归绘制分支前保存当前画家状态,绘制完成后恢复,这样就不会让平移、旋转操作互相干扰:
from PyQt5 import QtGui, QtWidgets, QtCore import sys class Arena(QtWidgets.QWidget): def __init__(self): super(Arena, self).__init__() self.angle = 45 self.recursions = 10 self.setGeometry(2500, 400, 500, 500) self.origin = (self.width()/2, self.height()) self.pal = QtGui.QPalette() self.pal.setColor(QtGui.QPalette.Background, QtGui.QColor(0, 0, 0)) self.setPalette(self.pal) self.pen_branch = QtGui.QPen() self.pen_branch.setColor(QtGui.QColor(255, 255, 255)) self.init_UI() def init_UI(self): self.slider_angle = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.slider_angle.setMinimum(-8000) self.slider_angle.setMaximum(8000) self.slider_angle.setGeometry(0, 50, self.width(), 50) self.slider_angle.valueChanged.connect(self.setAngleValue) self.setAngleValue(4500) self.slider_angle.setValue(4500) def setAngleValue(self, value): self.angle = value / 100 self.update() def branch(self, p, length): # 绘制当前分支 p.drawLine(0, 0, 0, -length) if length > 3: # 保存当前画家状态(平移、旋转等) p.save() # 移动到当前分支的末端 p.translate(0, -length) # 绘制左分支:旋转指定角度后递归 p.rotate(self.angle) self.branch(p, length * 0.66) # 恢复到保存的状态,准备绘制右分支 p.restore() # 再次保存状态,绘制右分支 p.save() p.translate(0, -length) # 旋转负角度,保证对称 p.rotate(-self.angle) self.branch(p, length * 0.66) p.restore() def paintEvent(self, e): p = QtGui.QPainter(self) p.setRenderHint(QtGui.QPainter.Antialiasing) p.setPen(self.pen_branch) p.drawText(20, 20, f'angle: {self.angle:.2f}') # 移动到画布底部中心,作为树干的起点 p.translate(self.width() / 2, self.height()) # 绘制树干并启动递归 self.branch(p, 100) if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) arena = Arena() arena.show() app.exec_()
关键改进点
- 使用
p.save()和p.restore()替代手动保存/设置transform,状态管理更可靠 - 左右分支的绘制逻辑完全对称:都是先平移到分支末端,再旋转对应角度后递归
- 移除了所有多余的平移、旋转操作,保证每个分支的起点位置正确
运行这段代码后,你拖动滑块调整角度时,就能得到完美对称的分形树了!
内容的提问来源于stack exchange,提问作者Pau
相关产品推荐
相关产品推荐

