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

如何用Tkinter和Matplotlib制作类Excel可滚动伸缩时间轴?

为Tkinter小程序实现带可伸缩滚动条的时间轴

我想用Tkinter做一个带可滚动功能的时间轴,目前已经能用Matplotlib动态生成并更新图表,但想要实现类似Excel时间轴的效果——能传入起止日期数据进行滚动。我试过ttkwidgets里的TimeLine组件,它自带滚动条和放大按钮,但没法同时实现伸缩功能,我的代码如下:

import tkinter as tk
from ttkwidgets import TimeLine

window = tk.Tk()
timeline = TimeLine(
    window,
    categories={str(key): {"text": "Category {}".format(key)} for key in range(0, 5)},
    height=100, extend=True
)
menu = tk.Menu(window, tearoff=False)
menu.add_command(label="Some Action", command=lambda: print("Command Executed"))
timeline.draw_timeline()
timeline.grid()
window.after(5000, lambda: print(timeline.time))
window.mainloop()

请问能不能给这个组件添加可伸缩滚动条?


可以通过扩展ttkwidgets.TimeLine的功能,或结合Tkinter原生组件实现同时支持滚动与伸缩的效果,以下是两种可行方案:

方案1:扩展ttkwidgets.TimeLine,绑定滚动与伸缩逻辑

ttkwidgets.TimeLine的extend=True参数已开启时间范围扩展能力,我们只需添加滚动条并绑定起止日期控制逻辑,就能实现需求:

import tkinter as tk
from ttkwidgets import TimeLine
from tkinter import ttk
import datetime

def update_timeline_range(start_date, end_date):
    # 将日期转换为时间戳适配TimeLine组件
    start_ts = start_date.timestamp()
    end_ts = end_date.timestamp()
    # 设置时间轴起止范围并刷新
    timeline.set_time_range(start_ts, end_ts)
    timeline.draw_timeline()

window = tk.Tk()
window.title("可伸缩滚动时间轴")

# 初始化TimeLine组件
timeline = TimeLine(
    window,
    categories={str(key): {"text": "Category {}".format(key)} for key in range(0, 5)},
    height=200,
    extend=True
)

# 添加水平滚动条并绑定
scrollbar = ttk.Scrollbar(window, orient="horizontal", command=timeline.xview)
timeline.configure(xscrollcommand=scrollbar.set)

# 添加起止日期控制栏
control_frame = ttk.Frame(window)
control_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=5)

ttk.Label(control_frame, text="起始日期:").grid(row=0, column=0, padx=2)
start_entry = ttk.Entry(control_frame)
start_entry.insert(0, "2024-01-01")
start_entry.grid(row=0, column=1, padx=2)

ttk.Label(control_frame, text="结束日期:").grid(row=0, column=2, padx=2)
end_entry = ttk.Entry(control_frame)
end_entry.insert(0, "2024-01-10")
end_entry.grid(row=0, column=3, padx=2)

def apply_date_range():
    try:
        start = datetime.datetime.strptime(start_entry.get(), "%Y-%m-%d")
        end = datetime.datetime.strptime(end_entry.get(), "%Y-%m-%d")
        update_timeline_range(start, end)
    except ValueError:
        print("日期格式错误,请输入YYYY-MM-DD")

ttk.Button(control_frame, text="应用", command=apply_date_range).grid(row=0, column=4, padx=5)

# 布局配置
timeline.grid(row=0, column=0, sticky="nsew")
scrollbar.grid(row=2, column=0, sticky="ew")
window.grid_rowconfigure(0, weight=1)
window.grid_columnconfigure(0, weight=1)

window.mainloop()

方案说明

  • 保留TimeLine原生的滚轮缩放、放大按钮功能,新增水平滚动条支持拖动滚动
  • 通过日期输入框可手动设置起止时间,实现精确的时间范围伸缩
  • 利用set_time_range方法直接控制时间轴显示范围,配合draw_timeline刷新界面

方案2:基于Canvas自定义时间轴(灵活性更高)

如果ttkwidgets组件限制较多,可直接用Tkinter Canvas实现完全自定义的时间轴,适配Excel样式:

import tkinter as tk
from tkinter import ttk
import datetime

class ScrollableTimeline(tk.Canvas):
    def __init__(self, parent, categories, **kwargs):
        super().__init__(parent, **kwargs)
        self.categories = categories
        self.cat_height = 40
        self.start_date = datetime.datetime(2024, 1, 1)
        self.end_date = datetime.datetime(2024, 1, 10)
        self.pixels_per_day = 50  # 每天对应像素宽度

        # 绑定滚动条
        self.scrollbar = ttk.Scrollbar(parent, orient="horizontal", command=self.xview)
        self.configure(xscrollcommand=self.scrollbar.set)

        # 绑定滚轮缩放事件
        self.bind("<MouseWheel>", self.on_zoom)
        self.bind("<Button-4>", self.on_zoom)
        self.bind("<Button-5>", self.on_zoom)

        self.draw_timeline()

    def draw_timeline(self):
        self.delete("all")
        # 绘制分类标签
        for idx, cat in enumerate(self.categories.values()):
            y_pos = idx * self.cat_height + 20
            self.create_text(10, y_pos, text=cat["text"], anchor="w")

        # 绘制时间刻度与轴线
        total_days = (self.end_date - self.start_date).days
        total_width = total_days * self.pixels_per_day
        self.configure(scrollregion=(0, 0, total_width, len(self.categories)*self.cat_height))

        for day in range(total_days + 1):
            current_date = self.start_date + datetime.timedelta(days=day)
            x_pos = day * self.pixels_per_day
            self.create_line(x_pos, 0, x_pos, len(self.categories)*self.cat_height, fill="#ccc")
            self.create_text(x_pos, 5, text=current_date.strftime("%m-%d"), anchor="n")

    def on_zoom(self, event):
        # 滚轮向上放大,向下缩小,限制最小缩放比例
        delta = event.delta if hasattr(event, "delta") else -1 if event.num == 5 else 1
        if delta > 0:
            self.pixels_per_day = max(10, self.pixels_per_day - 5)
        else:
            self.pixels_per_day += 5
        self.draw_timeline()

    def set_date_range(self, start, end):
        self.start_date = start
        self.end_date = end
        self.draw_timeline()

window = tk.Tk()
window.title("自定义可伸缩滚动时间轴")

# 初始化自定义时间轴
categories = {str(key): {"text": "Category {}".format(key)} for key in range(0, 5)}
timeline = ScrollableTimeline(window, categories, height=200, bg="white")

# 添加日期控制栏
control_frame = ttk.Frame(window)
control_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=5)

ttk.Label(control_frame, text="起始日期:").grid(row=0, column=0, padx=2)
start_entry = ttk.Entry(control_frame)
start_entry.insert(0, "2024-01-01")
start_entry.grid(row=0, column=1, padx=2)

ttk.Label(control_frame, text="结束日期:").grid(row=0, column=2, padx=2)
end_entry = ttk.Entry(control_frame)
end_entry.insert(0, "2024-01-10")
end_entry.grid(row=0, column=3, padx=2)

def apply_dates():
    try:
        start = datetime.datetime.strptime(start_entry.get(), "%Y-%m-%d")
        end = datetime.datetime.strptime(end_entry.get(), "%Y-%m-%d")
        timeline.set_date_range(start, end)
    except ValueError:
        print("日期格式错误,请输入YYYY-MM-DD")

ttk.Button(control_frame, text="应用", command=apply_dates).grid(row=0, column=4, padx=5)

# 布局配置
timeline.grid(row=0, column=0, sticky="nsew")
timeline.scrollbar.grid(row=2, column=0, sticky="ew")
window.grid_rowconfigure(0, weight=1)
window.grid_columnconfigure(0, weight=1)

window.mainloop()

方案说明

  • 完全基于Canvas实现,可自由定制时间轴样式、刻度密度、交互逻辑
  • 支持鼠标滚轮缩放、滚动条拖动,以及手动设置起止日期
  • 可轻松扩展添加任务块、标记点等功能,更贴近Excel时间轴的使用体验

内容的提问来源于stack exchange,提问作者Simon Joubert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:20:35