You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新手求助:如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:45:57