Q:

How do i create a countdown timer in ModalView after pressing a button?

I am trying to create a modalview with a timer in it. Upon pressing the "begin" button, a modal view should appear and the countdown should start. However, I am getting an valueerror message. ValueError: TimerView.timer has an invalid format (got main.TimerView object at 0x0000017AD40D6180>>>).May I know which part of the code is wrong? Thanks in advance.
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition, WipeTransition, NoTransition, SlideTransition
from kivymd.theming import ThemeManager
from kivy.properties import StringProperty, NumericProperty
from kivy.uix.modalview import ModalView
from kivymd.uix.label import MDLabel
from kivy.clock import Clock

class TimerView(ModalView):
    number = NumericProperty(15)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.background = "transparent_image.png"
        self.background_color = [1/3,1/3,1/3,0.8]
        self.auto_dismiss = False
        self.size_hint = (None,None)
        self.size = (150,50)
        timer_countdown = MDLabel(font_style = 'H1', theme_text_color = 'Primary',
                                  text = str(self.number), halign = 'center',
                                  text_color = (1,1,1,1), size_hint_y = None)
        self.add_widget(timer_countdown)

    def decrement_time(self, dt):
        self.number -= 1

    def start(self,*args):
        self.timer = Clock.schedule_interval(self.decrement_time, 1)

    def stop(self):
        Clock.unschedule(self.timer)

class MainScreen(Screen):
    pass

class BeginScreen(Screen):
    pass

class MyScreenManager(ScreenManager):

    def __init__(self,**kwargs):
        super().__init__(**kwargs)
        self.view = TimerView()

    def open_view(self):
        self.view.bind(on_open=self.view.start)
        self.view.open()

main_widget_kv = ('''
#: import ScrollEffect kivy.effects.scroll.ScrollEffect

MyScreenManager:
    BeginScreen:

<BeginScreen>:
    begin_button:begin_button
    name: "begin"
    canvas.before:
        Color: 
            rgb: .1, .1, .1
    FloatLayout:
        id: begin_layout
        Button:
            id: begin_button
            text: 'Begin'
            font_size: 24
            on_press: app.root.open_view()
            size_hint: (.4,.25)
            pos_hint: {"center_x":.5, "center_y":.2}
            color: [0,0,0,1]

''')

class TestApp(MDApp):

    def __init__(self,**kwargs):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Red"
        super().__init__(**kwargs)

    def build(self):
        main_widget = Builder.load_string(main_widget_kv)
        return main_widget

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

A:

When you set the text of a Label in python code, it uses the value at that time, and will not change automatically. If you do the same thing in kv, it will update automatically (provided that the text references a Property). So just changing self.number has no effect on your timer_countdown Label.
So, you need to update that text explicitly. Here is a modified version of your code that does that:
class TimerView(ModalView):
    number = NumericProperty(15)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.background = "transparent_image.png"
        self.background_color = [1/3,1/3,1/3,0.8]
        self.auto_dismiss = False
        self.size_hint = (None,None)
        self.size = (150,50)
        self.timer_countdown = MDLabel(font_style = 'H1', theme_text_color = 'Primary',
                                  text = str(self.number), halign = 'center',
                                  text_color = (1,1,1,1), size_hint_y = None)
        self.add_widget(self.timer_countdown)

    def decrement_time(self, dt):
        self.number -= 1
        # self.timer_countdown.text = str(self.number)

    def on_number(self, instance, value):
        self.timer_countdown.text = str(value)

    def start(self,*args):
        self.t = Clock.schedule_interval(self.decrement_time, 1)

    def stop(self):
        Clock.unschedule(self.t)

A reference to the MDLabel is kept in self.timer_countdown and the on_number() method gets executed whenever number changes, and just updates the MDLabel. Note that you can also do the update by just uncommenting the line:
# self.timer_countdown.text = str(self.number)

In that case, number does not need to be a Property, and the on_number() method is not needed.

