使用 Kivy 同时显示多个时钟

Posted

技术标签:

【中文标题】使用 Kivy 同时显示多个时钟【英文标题】:Displaying multiple clocks simultaneously with Kivy 【发布时间】:2021-12-30 14:36:42 【问题描述】:

使用 Kivy 2.0.0 和 Python 2.9.9

刚开始学习 Kivy,我正在尝试同时显示三个自定义时钟(目前使用当前时间)。理想情况下,我希望能够将三个时钟分配给 GridLayout 或 BoxLayout 中的位置,但现在我只想能够同时显示三个时钟。

我尝试修改 kv 文件以将我的时钟的多次迭代嵌套在 GridLayout 中,并且我尝试将它们拆分为多个 kv 文件并从 python 端单独构建每个文件。它总是要么将时钟绘制在彼此之上,要么给我一个错误。

非常感谢您的指导和建议。提前谢谢你。

我修改了this code,为我的时钟生成了以下 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 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.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):
        clock = MyClockWidget()
        Clock.schedule_interval(clock.ticks.update_clock, 0.1)
        return clock

if __name__ == '__main__':
    MyDashApp().run()

还有这个kv文件:

#:kivy 2.0.0

#:import math math

<ClockNumber@Label>:
    i: 0
    text: str(self.i)
    pos_hint: "center_x": 0.5+0.42*math.sin(math.pi/12*(self.i-12) + math.pi/2), "center_y": 0.5+0.42*math.cos(math.pi/12*(self.i-12) + math.pi/2)
    font_size: self.height/16
    color: 125.0/255.0, 253.0/255.0, 254.0/255.0

<MyClockWidget>:
    face: face
    ticks: ticks
    FloatLayout:
        id: face
        size_hint: None, None
        pos_hint: "center_x":0.5, "center_y":0.5
        size: 0.9*min(root.size), 0.9*min(root.size)

        ClockNumber:
            i: 0        
        ClockNumber:
            i: 1
        ClockNumber:
            i: 2
        ClockNumber:
            i: 3
        ClockNumber:
            i: 4
        ClockNumber:
            i: 5
        ClockNumber:
            i: 6
        ClockNumber:
            i: 7
        ClockNumber:
            i: 8
        ClockNumber:
            i: 9
        ClockNumber:
            i: 10
        ClockNumber:
            i: 11
        ClockNumber:
            i: 12
    
    Ticks:
        id: ticks
        r: min(root.size)*0.9/2

【问题讨论】:

【参考方案1】:

您的代码几乎可以工作了。我认为主要问题是kv 中的Ticks 小部件需要设置其位置。尝试将 kv 中的内容更改为:

Ticks:
    id: ticks
    pos_hint: face.pos_hint
    r: min(root.size)*0.9/2

我有三个时钟出现并更新如下:

class MyDashApp(App):
    def build(self):
        root = GridLayout(cols=3)
        for _i in range(3):
            clock = MyClockWidget()
            Clock.schedule_interval(clock.ticks.update_clock, 0.1)
            root.add_widget(clock)
        return root

【讨论】:

以上是关于使用 Kivy 同时显示多个时钟的主要内容,如果未能解决你的问题,请参考以下文章

Kivy 中的数字时钟标签

使 Kivy TextInput 框架不可见但显示文本

kivy python 闪烁文字

怎么让XP桌面右下角显示多个时钟

如何使用 intteruptible kivy 时钟?

使用 Kivy 的时钟从 kivy 文件 (.kv) 访问不同类的 id/widget?