【问题标题】:Making a clock in kivy用kivy制作时钟
【发布时间】:2013-09-26 05:29:05
【问题描述】:

我是 Kivy 的新手,我正在努力更好地处理事件以及框架的一些基础知识。

为此,谁能提供在 Kivy 中实现的简单时钟的代码,它显示当前时间并每秒更新一次?

【问题讨论】:

    标签: python kivy


    【解决方案1】:

    一个简单的图形呢:

    EDIT (12.02.2022):重构整个代码,使其更具可读性

    import collections
    import datetime
    import math
    
    from kivy.app import App
    from kivy.uix.floatlayout import FloatLayout
    from kivy.uix.label import Label
    from kivy.clock import Clock
    from kivy.lang import Builder
    from kivy.graphics import Color, Line
    
    Builder.load_string('''
    <MyClockWidget>:
        on_pos: self.update_clock()
        on_size: self.update_clock()
        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)
            canvas:
                Color:
                    rgb: 0.1, 0.1, 0.1
                Ellipse:
                    size: self.size
                    pos: self.pos
        FloatLayout
            id: hands
            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)
    ''')
    
    Position = collections.namedtuple('Position', 'x y')
    
    
    class MyClockWidget(FloatLayout):
        def on_parent(self, myclock, parent):
            """
            Add number labels when added in widget hierarchy
            """
            for i in range(1, 13):
                number = Label(
                    text=str(i),
                    pos_hint={
                        # pos_hint is a fraction in range (0, 1)
                        "center_x": 0.5 + 0.45*math.sin(2 * math.pi * i/12),
                        "center_y": 0.5 + 0.45*math.cos(2 * math.pi * i/12),
                    }
                )
                self.ids["face"].add_widget(number)
    
        def position_on_clock(self, fraction, length):
            """
            Calculate position in the clock using trygonometric functions
            """
            center_x = self.size[0]/2
            center_y = self.size[1]/2
            return Position(
                center_x + length * math.sin(2 * math.pi * fraction),
                center_y + length * math.cos(2 * math.pi * fraction),
            )
    
        def update_clock(self, *args):
            """
            Redraw clock hands
            """
            time = datetime.datetime.now()
            hands = self.ids["hands"]
            seconds_hand = self.position_on_clock(time.second/60, length=0.45*hands.size[0])
            minutes_hand = self.position_on_clock(time.minute/60+time.second/3600, length=0.40*hands.size[0])
            hours_hand = self.position_on_clock(time.hour/12 + time.minute/720, length=0.35*hands.size[0])
    
            hands.canvas.clear()
            with hands.canvas:
                Color(0.2, 0.5, 0.2)
                Line(points=[hands.center_x, hands.center_y, seconds_hand.x, seconds_hand.y], width=1, cap="round")
                Color(0.3, 0.6, 0.3)
                Line(points=[hands.center_x, hands.center_y, minutes_hand.x, minutes_hand.y], width=2, cap="round")
                Color(0.4, 0.7, 0.4)
                Line(points=[hands.center_x, hands.center_y, hours_hand.x, hours_hand.y], width=3, cap="round")
    
    
    class MyApp(App):
        def build(self):
            clock_widget = MyClockWidget()
            # update initially, just after construction of the widget is complete
            Clock.schedule_once(clock_widget.update_clock, 0)
            # then update every second
            Clock.schedule_interval(clock_widget.update_clock, 1)
            return clock_widget
    
    
    if __name__ == '__main__':
        MyApp().run()
    

    旧答案

    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
    from kivy.properties import NumericProperty
    
    import datetime
    
    kv = '''
    #:import math math
    
    [ClockNumber@Label]:
        text: str(ctx.i)
        pos_hint: {"center_x": 0.5+0.42*math.sin(math.pi/6*(ctx.i-12)), "center_y": 0.5+0.42*math.cos(math.pi/6*(ctx.i-12))}
        font_size: self.height/16
    
    <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)
            canvas:
                Color:
                    rgb: 0.1, 0.1, 0.1
                Ellipse:
                    size: self.size     
                    pos: self.pos
            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
    '''
    Builder.load_string(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.datetime.now()
                Color(0.2, 0.5, 0.2)
                Line(points=[self.center_x, self.center_y, self.center_x+0.8*self.r*sin(pi/30*time.second), self.center_y+0.8*self.r*cos(pi/30*time.second)], width=1, cap="round")
                Color(0.3, 0.6, 0.3)
                Line(points=[self.center_x, self.center_y, self.center_x+0.7*self.r*sin(pi/30*time.minute), self.center_y+0.7*self.r*cos(pi/30*time.minute)], width=2, cap="round")
                Color(0.4, 0.7, 0.4)
                th = time.hour*60 + time.minute
                Line(points=[self.center_x, self.center_y, self.center_x+0.5*self.r*sin(pi/360*th), self.center_y+0.5*self.r*cos(pi/360*th)], width=3, cap="round")
    
    class MyClockApp(App):
        def build(self):
            clock = MyClockWidget()
            Clock.schedule_interval(clock.ticks.update_clock, 1)
            return clock
    
    if __name__ == '__main__':
        MyClockApp().run()
    

    【讨论】:

    • 我对你的例子很着迷。 (我也是 Kivy 的新手)对我来说几乎没有什么不清楚的。您实例化clock = MyClockWidget() 而MyClockWidget 没有实现它只继承FloatLayout。但是下一行你有 Clock.schedule_interval(clock.ticks.update_clock, 1) 为什么时钟有属性滴答?它与您的 kv 文件中的“滴答声:滴答声”有关吗?但老实说什么是蜱:蜱我也不明白 :) 我不明白的另一件事是更大的图景。为什么它不能在一个可以添加到任何地方的小部件/类上形成?
    • @user2997497 最初它应该是一个快速而肮脏的例子,但它在 Stack Overflow 九年后不知何故积累了很多选票。我不认为这段代码特别漂亮,我相信这是开始学习框架的一个相当人为的例子。无论如何,Clock 是内部 Kivy 的 Clock 类,clock(注意它不是大写的)是保存小部件的变量名称。所以Clock.schedule_interval(clock.ticks.update_clock, 1) 调用 Kivy 的调度程序每秒调用update_clock 来画手。
    • Ticks 应该更名为Hands,因为它拥有它们(当时我的英语失败了,因为我不是母语人士)。我将此小部件添加到 kv 布局中的 MyClockWidget 中,并且此 ticks: ticks 事物允许我在代码之外引用它。我认为您可以跳过它,只需 call clock.ids['ticks'] 即可进入现代 Kivy 代码中的这个变量(我认为当时它有点复杂)。
    • @user2997497 我重构了整个示例,希望它现在更具可读性
    【解决方案2】:

    这是一个非常简单的时钟:

    from kivy.app import App
    from kivy.uix.label import Label
    from kivy.clock import Clock
    
    import time
    
    class IncrediblyCrudeClock(Label):
        def update(self, *args):
            self.text = time.asctime()
    
    class TimeApp(App):
        def build(self):
            crudeclock = IncrediblyCrudeClock()
            Clock.schedule_interval(crudeclock.update, 1)
            return crudeclock
    
    if __name__ == "__main__":
        TimeApp().run()
    

    【讨论】:

      猜你喜欢
      • 2015-07-23
      • 2018-05-10
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 2021-12-30
      相关资源
      最近更新 更多