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

Python Kivy Garden Graph如何用datetime对象替代浮点数绘图?

我之前也遇到过kivy.garden.Graph不支持datetime对象的问题,核心原因是这个组件的底层设计只接受数值型(浮点数/整数)的坐标输入,所以直接传datetime肯定不行,但我们可以通过日期→数值映射+自定义轴标签的方式完美解决这个需求,下面是具体的实现思路和代码示例:

核心思路

kivy.garden.Graph的绘图系统依赖数值坐标,所以需要做两步转换:

  1. 正向转换:把datetime对象转换成可用于绘图的浮点数(比如时间戳、相对于起始日期的天数)
  2. 反向转换:自定义X轴的标签渲染逻辑,把绘图用的浮点数再转回人类可读的日期字符串

具体实现步骤

1. 准备数据:日期转浮点数

你可以选择两种常见的映射方式:

  • 时间戳:把datetime转成Unix时间戳(从1970-01-01开始的秒数,浮点数),适合跨度较大的日期范围
  • 相对天数:计算每个日期相对于起始日期的天数,适合跨度较小的场景,避免时间戳数值过大,也兼容1970年之前的日期

示例代码:

from datetime import datetime, timedelta

# 原始日期-资产价格数据
date_price_pairs = [
    (datetime(2015, 1, 1), 100.0),
    (datetime(2016, 2, 15), 125.3),
    (datetime(2017, 6, 30), 148.9),
    (datetime(2018, 1, 1), 142.5),
]

# 方式1:转时间戳
x_timestamps = [dt.timestamp() for dt, _ in date_price_pairs]
y_prices = [price for _, price in date_price_pairs]

# 方式2:转相对天数(推荐,兼容性更强)
start_date = datetime(2015, 1, 1)
x_relative_days = [(dt - start_date).days for dt, _ in date_price_pairs]

2. 自定义Graph类,重写X轴标签渲染

我们需要继承Graph类,重写get_x_label方法,把绘图用的浮点数转回日期字符串:

from kivy.garden.graph import Graph, MeshLinePlot

class DateAxisGraph(Graph):
    def __init__(self, start_date=None, use_timestamps=False, **kwargs):
        super().__init__(**kwargs)
        self.start_date = start_date  # 相对天数模式下的起始日期
        self.use_timestamps = use_timestamps  # 标记是否使用时间戳模式

    def get_x_label(self, x):
        # 根据模式把浮点数转回datetime
        if self.use_timestamps:
            dt = datetime.fromtimestamp(x)
        else:
            dt = self.start_date + timedelta(days=int(x))
        # 自定义日期格式,可根据需求调整(比如"%Y年%m月")
        return dt.strftime("%Y-%m-%d")

3. 整合绘图,运行应用

把转换后的数据传入自定义的Graph,添加折线图即可:

from kivy.app import App

class AssetPriceApp(App):
    def build(self):
        # 使用相对天数模式创建折线图
        plot = MeshLinePlot(color=[0.2, 0.6, 1, 1])  # 蓝色折线
        plot.points = list(zip(x_relative_days, y_prices))

        # 创建自定义日期图表
        graph = DateAxisGraph(
            start_date=start_date,
            use_timestamps=False,
            xlabel="日期",
            ylabel="资产价格",
            x_range=(min(x_relative_days), max(x_relative_days)),
            y_range=(min(y_prices)-10, max(y_prices)+10),
            x_ticks_major=365,  # 每一年显示一个主刻度
            x_ticks_minor=90,   # 每季度显示一个次刻度
            size_hint=(1, 0.8),
            pos_hint={"top": 0.9}
        )
        graph.add_plot(plot)
        return graph

if __name__ == "__main__":
    AssetPriceApp().run()

注意事项

  • 如果你的日期包含1970年之前的时间,不要用时间戳模式,因为datetime.timestamp()在这种情况下会抛出异常,相对天数模式是更安全的选择
  • 可以根据需求调整strftime的格式字符串,比如改成"%Y年%m月"更符合中文习惯
  • 如果需要更精细的X轴刻度控制,可以调整x_ticks_major和x_ticks_minor的数值,避免标签重叠

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:35:40