Home > Back-end >  Displaying multiple clocks simultaneously with Kivy
Displaying multiple clocks simultaneously with Kivy

Time:11-24

Using Kivy 2.0.0 and Python 2.9.9

Just started learning Kivy and I'm trying to display three custom clocks simultaneously (using the current time for now). Ideally, I want to be able to get the three clocks to be assignable to locations in a GridLayout or BoxLayout but for now I just want to be able to display three clocks at the same time.

I've tried modifying the kv file to nest multiple iterations of my clock in a GridLayout and I've tried splitting them up over several kv files and building each one individually from the python side. It always either draws the clocks on top of each other or gives me an error.

Direction and advice is much appreciated. Thank you in advance.

I modified this code to produce the following Python Code for my clock:

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()

and this kv file:

#: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

CodePudding user response:

You code is almost working. I think the main problem is that your Ticks widget in the kv needs its position set. Try changing that in the kv to:

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

And I got three clocks to appear and update like this:

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
  • Related