新手求助:如何在Tkinter环形图表中将刻度0置于左侧
Tkinter环形图表:把刻度0放到左侧的解决方案
问题出在哪
咱们用的数学库默认极坐标0度指向右侧(x轴正方向),但你要0刻度在左侧(x轴负方向),所以得给所有刻度的角度加180度(也就是π弧度)偏移。另外你代码里的刻度列表是重复的旧数据,得换成你实际要的[0,45,90,174,178,90,-45]。
修改后的完整代码
import tkinter as tk import math class CircleArrowApp: def __init__(self, master): self.master = master master.title("HORSTFX") self.radius = 100 # 初始圆半径 # 第一个圆环和箭头 self.canvas1 = tk.Canvas(master, width=400, height=400, bg='white', highlightbackground='goldenrod', highlightthickness=15) self.canvas1.pack(side=tk.LEFT, padx=20) self.angle1 = 0 self.arrow1 = None # 原代码绑定空事件会报错,先注释掉,需要resize的话再补充实现 # self.canvas1.bind("", self.on_canvas1_resize) # 第二个圆环和箭头 self.canvas2 = tk.Canvas(master, width=400, height=400, bg='white', highlightbackground='goldenrod', highlightthickness=15) self.canvas2.pack(side=tk.LEFT, padx=20) self.angle2 = 0 self.arrow2 = None # self.canvas2.bind("", self.on_canvas2_resize) # 按钮框架 self.button_frame = tk.Frame(master) self.button_frame.pack(side=tk.BOTTOM, padx=10) self.start_button = tk.Button(self.button_frame, text="START", width=10, command=self.start_animation) self.start_button.pack(side=tk.TOP, pady=10) self.stop_button = tk.Button(self.button_frame, text="STOP", width=10, command=self.stop_animation) self.stop_button.pack(side=tk.TOP, pady=10) self.plus_button = tk.Button(self.button_frame, text="+", width=10, command=self.plus_function) self.plus_button.pack(side=tk.TOP, pady=10) self.minus_button = tk.Button(self.button_frame, text="-", width=10, command=self.minus_function) self.minus_button.pack(side=tk.TOP, pady=10) self.animating = False # 初始化绘制 self.update_circle_arrows() def start_animation(self): self.animating = True def stop_animation(self): self.animating = False def plus_function(self): self.radius += 10 self.update_circle_arrows() def minus_function(self): if self.radius > 10: self.radius -= 10 self.update_circle_arrows() def update_circle_arrows(self): # 清空画布,避免重复绘制叠加 self.canvas1.delete("all") self.canvas2.delete("all") # 重新绘制两个圆环 self.draw_circle_arrow(self.canvas1, self.angle1) self.draw_circle_arrow(self.canvas2, self.angle2) def draw_circle_arrow(self, canvas, angle): center_x = canvas.winfo_width() // 2 center_y = canvas.winfo_height() // 2 inner_radius = self.radius * 0.8 # 绘制圆环 canvas.create_oval(center_x - inner_radius, center_y - inner_radius, center_x + inner_radius, center_y + inner_radius, outline='goldenrod', fill='white', width=8) # 箭头终点计算(如果需要箭头也以左侧0为基准,就加math.pi偏移) end_x = center_x + inner_radius * math.cos(angle + math.pi) end_y = center_y + inner_radius * math.sin(angle + math.pi) start_x = center_x start_y = center_y if canvas == self.canvas1: if self.arrow1: canvas.delete(self.arrow1) self.arrow1 = canvas.create_line(start_x, start_y, end_x, end_y, arrow=tk.LAST, fill='goldenrod', width=6) # 你要求的刻度列表 outer_radius = inner_radius + 20 for scale_num in [0,45,90,174,178,90,-45]: # 核心:把刻度角度转弧度后加π,让0度指向左侧 angle_rad = math.radians(scale_num) + math.pi num_x = center_x + outer_radius * math.cos(angle_rad) num_y = center_y + outer_radius * math.sin(angle_rad) canvas.create_text(num_x, num_y, text=str(scale_num), fill='black') # 绘制外层细圈 outer_radius = inner_radius + 2 canvas.create_oval(center_x - outer_radius, center_y - outer_radius, center_x + outer_radius, center_y + outer_radius, outline='', width=2) elif canvas == self.canvas2: if self.arrow2: canvas.delete(self.arrow2) self.arrow2 = canvas.create_line(start_x, start_y, end_x, end_y, arrow=tk.LAST, fill='goldenrod', width=6) # 第二个圆环同样应用刻度 outer_radius = inner_radius + 20 for scale_num in [0,45,90,174,178,90,-45]: angle_rad = math.radians(scale_num) + math.pi num_x = center_x + outer_radius * math.cos(angle_rad) num_y = center_y + outer_radius * math.sin(angle_rad) canvas.create_text(num_x, num_y, text=str(scale_num), fill='black') def animate(self): if self.animating: # 动画角度递增,可根据需求调整速度 self.angle1 += 0.05 self.angle2 += 0.03 self.update_circle_arrows() self.master.after(10, self.animate) if __name__ == "__main__": root = tk.Tk() app = CircleArrowApp(root) root.mainloop()
核心调整内容
- 角度偏移:给每个刻度的弧度值加上
math.pi(180度),直接把0度从右侧转到左侧:angle_rad = math.radians(scale_num) + math.pi - 更新刻度列表:把原来重复的旧刻度换成你需要的
[0,45,90,174,178,90,-45] - 修复重复绘制:加了
update_circle_arrows方法,每次操作后清空画布再重绘,避免内容叠加 - 完善动画逻辑:补全了
animate方法的实际更新代码,解决原代码初始化不绘制的问题 - 移除无效绑定:原代码里的空事件绑定会报错,已经注释掉了
这样改完之后,0刻度就会准确出现在图表左侧,其他刻度也会按你要的顺序排列。
内容的提问来源于stack exchange,提问作者Moysés Requiao
相关产品推荐
相关产品推荐

