Kivy开发:实现多个自定义时钟同时显示的布局问题求解
解决方案
核心修改点
- 引入布局容器统一管理多个时钟实例,每个时钟会自动分配独立渲染空间,避免重叠
- 为每一个时钟实例单独绑定定时器更新事件,保证所有时钟正常走时
注:官方不存在Python 2.9.9版本,你实际使用的应该是Python 3.9.x,Kivy 2.0.0适配Python 3.6~3.9版本,注意版本匹配避免运行错误
完整修改后的Python代码
from kivy.app import App from kivy.uix.widget import Widget from kivy.graphics import Color, Line from kivy.uix.floatlayout import FloatLayout from kivy.uix.boxlayout import BoxLayout from math import cos, sin, pi from kivy.clock import Clock from kivy.lang import Builder import os from datetime import datetime # 路径拼接优化为跨平台写法 Builder.load_file(os.path.join(os.path.dirname(os.path.realpath(__file__)), "clock.kv")) class MyClockWidget(FloatLayout): pass class Ticks(Widget): def __init__(self, **kwargs): super(Ticks, self).__init__(**kwargs) self.bind(pos=self.update_clock) self.bind(size=self.update_clock) def update_clock(self, *args): self.canvas.clear() with self.canvas: time = datetime.now() for s in range(0, time.second+1): if s < 30: Color(125.0/255.0, 253.0/255.0, 254.0/255.0) elif s >= 30 and s < 45: Color(255.0/255.0, 95.0/255.0, 31.0/255.0) else: Color(255.0/255.0, 49.0/255.0, 49.0/255.0) Line(points = [ self.center_x + 0.5*self.r*sin(pi/60*s - pi/2), self.center_y + 0.5*self.r*cos(pi/60*s - pi/2), self.center_x + 0.795*self.r*sin(pi/60*s - pi/2), self.center_y + 0.795*self.r*cos(pi/60*s - pi/2) ], width=2, cap="none" ) for m in range(0, time.minute + 1): Color(125.0/255.0, 253.0/255.0, 254.0/255.0) Line(points = [ self.center_x + 0.3*self.r*sin(pi/60*m - pi/2), self.center_y + 0.3*self.r*cos(pi/60*m - pi/2), self.center_x + 0.495*self.r*sin(pi/60*m - pi/2), self.center_y + 0.495*self.r*cos(pi/60*m - pi/2) ], width=2, cap="none" ) if time.hour < 12: hr = time.hour else: hr = time.hour - 12 for h in range(0, hr + 1): Color(125.0/255.0, 253.0/255.0, 254.0/255.0) Line(points = [ self.center_x + 0.2*self.r*sin(pi/12*h - pi/2), self.center_y + 0.2*self.r*cos(pi/12*h - pi/2), self.center_x + 0.295*self.r*sin(pi/12*h - pi/2), self.center_y + 0.295*self.r*cos(pi/12*h - pi/2) ], width=2, cap="none" ) th = h*60 + time.minute Color(125.0/255.0, 253.0/255.0, 254.0/255.0) Line(points=[self.center_x + 0.2*self.r*sin(pi/720*th - pi/2), self.center_y + 0.2*self.r*cos(pi/720*th - pi/2), self.center_x + 0.295*self.r*sin(pi/720*th - pi/2), self.center_y + 0.295*self.r*cos(pi/720*th - pi/2)], width=2, cap="none") class MyDashApp(App): def build(self): # 水平BoxLayout,3个时钟各占1/3宽度,添加边距避免时钟边缘贴边 root = BoxLayout(orientation='horizontal', spacing=10, padding=10) for _ in range(3): clock = MyClockWidget() # 每个时钟单独绑定更新定时器 Clock.schedule_interval(clock.ticks.update_clock, 0.1) root.add_widget(clock) return root if __name__ == '__main__': MyDashApp().run()
kv文件说明
原有clock.kv无需任何修改,已经完成了单个时钟的样式、刻度、数字的封装,可以直接复用。
布局调整方案
如果需要修改时钟的摆放规则,可按需求替换布局容器:
- 要使用网格排列,将BoxLayout替换为
GridLayout,设置cols=2/rows=3等参数即可自动按网格排列 - 要指定时钟固定位置,可将根布局改为FloatLayout,给每个
MyClockWidget单独设置size_hint和pos_hint属性即可放到任意位置 - 要实现不同时钟显示不同时间,只需给
Ticks类添加自定义时间参数,替换代码中datetime.now()的部分即可
内容的提问来源于stack exchange,提问作者JYPerez
相关产品推荐
相关产品推荐

