Как создать таймер обратного отсчета в ModalView после нажатия кнопки? - PullRequest
0 голосов
/ 17 марта 2020

Я пытаюсь создать модальное представление с таймером в нем. После нажатия кнопки «начать» должен появиться модальный вид и должен начаться обратный отсчет. Тем не менее, я получаю сообщение об ошибке valueerror. ValueError: TimerView.timer имеет недопустимый формат (получил объект main.TimerView по адресу 0x0000017AD40D6180 >>>). Могу я узнать, какая часть кода неверна? Заранее спасибо.

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

1 Ответ

1 голос
/ 18 марта 2020

Когда вы устанавливаете text кода Label в python, оно использует значение в это время и не изменится автоматически. Если вы сделаете то же самое в kv, оно обновится автоматически (при условии, что text ссылается на Property). Так что просто изменение self.number не влияет на timer_countdown Label.

Итак, вам нужно явно обновить text. Вот модифицированная версия вашего кода, которая делает это:

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)

Ссылка на MDLabel хранится в self.timer_countdown, и метод on_number() выполняется при каждом изменении number, и просто обновляет MDLabel. Обратите внимание, что вы также можете выполнить обновление, просто раскомментировав строку:

# self.timer_countdown.text = str(self.number)

В этом случае number не обязательно должен быть Property, а метод on_number() не нужен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...