Christopher Tan
Christopher Tan

Reputation: 53

Newbie at Kivy trying to create stopwatch

I'm attempting to create a stopwatch in Kivy. I've completed a skeleton on Sublime Text 3 (as shown in the code below). When I run the code on Sublime Text, a window opens, but Python crashes in 4.1s.

Here is the code in question:

import kivy

from kivy.app import App

from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.properties import NumericProperty

from kivy.lang import Builder

import time

class CrudeTimerGrid(GridLayout):
    # Initialise timer with input start time
    def __init__(self,start_time):
        time = NumericProperty(start_time)

    def tick(self):
        if self.time > 0:
            self.time -= 1
        else:
            pass

    def start(self):
        Clock.schedule_interval(self.tick,1)

    def pause(self):
        Clock.unschedule()

    # incomplete code
    def reset(self):
        pass


class CrudeTimerApp(App):
    def build(self):
        # Testing timer by initialising timer with 20 seconds
        return CrudeTimerGrid(20)

Builder.load_string('''
<CrudeTimerGrid>
    id: timer
    rows: 2
    # insert formatting here

    BoxLayout:
        Label:
            text: timer.time

    BoxLayout:

        Button:
            text: "Start"
            on_press: timer.start()

        Button:
            text: "Pause"
            on_press: timer.pause()

        Button:
            text: "Reset"
            on_press: timer.reset()
''')

CrudeTimerApp().run()

Newbie at StackOverflow too, so please let me know if any other info is needed. Thanks for your help!

Upvotes: 3

Views: 1150

Answers (1)

Mikhail Gerasimov
Mikhail Gerasimov

Reputation: 39546

Main problem is here:

def __init__(self,start_time):
    time = NumericProperty(start_time)

You should define Kivy properties at class level, please read this. Code'll stop crash if you change it like this:

class CrudeTimerGrid(GridLayout):
    time = NumericProperty(0)

There're also few other changes you should do to make it finally work, here's full code version:

import kivy

from kivy.app import App

from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.properties import NumericProperty

from kivy.lang import Builder

import time

class CrudeTimerGrid(GridLayout):
    time = NumericProperty(0)

    def tick(self, *_):
        if self.time > 0:
            self.time -= 1
        else:
            pass

    def start(self, *_):
        self.cb = Clock.schedule_interval(self.tick,1)

    def pause(self):
        Clock.unschedule(self.cb)

    # incomplete code
    def reset(self, *_):
        pass


class CrudeTimerApp(App):
    def build(self):
        # Testing timer by initialising timer with 20 seconds
        return CrudeTimerGrid(time=20)

Builder.load_string('''
<CrudeTimerGrid>
    id: timer
    rows: 2
    # insert formatting here

    BoxLayout:
        Label:
            text: str(timer.time)

    BoxLayout:

        Button:
            text: "Start"
            on_press: timer.start()

        Button:
            text: "Pause"
            on_press: timer.pause()

        Button:
            text: "Reset"
            on_press: timer.reset()
''')

CrudeTimerApp().run()

Upd:

Any idea why 2 arguments are input into tick in the first place?

tick passed to Clock.schedule_interval to be called. This function schedules it's callback with additional parameter (as many other functions in Kivy also do). You can read a bit more about it in documentation.

You defined self.cb in order to reference it in Clock.unschedule, correct?

You can schedule many different functions with different intervals calling Clock.schedule_interval multiple times. But how can Clock.unschedule know which concrete of them to unschedule? In order to make Clock.unschedule know what to unschedule you should pass to it value returned by Clock.schedule_interval. Here's documentation section where this mechanism described.

Upvotes: 2

Related Questions