Киви: Как запустить одну и ту же функцию на нескольких экранах - PullRequest
0 голосов
/ 05 июля 2019

Я пытаюсь сделать таймер, который будет отсчитывать до нуля от случайного начального числа несколько раз, пока не будет достигнут предопределенный лимит времени.Мне удалось сделать это на одном экране, но у меня возникли проблемы с его адаптацией к нескольким экранам.

В настоящее время, если я запускаю функции в классе PleaseWork (boxLayout), он делает именно так, как должен.Однако я хотел бы добавить некоторые экраны, чтобы на главном экране была кнопка с надписью «Вперед!»и при отпускании кнопки запускается таймер.Я хотел бы иметь возможность циклически переходить со второго на третий экран, при этом значение на таймере будет точно таким же, но я не уверен, как это сделать.

Py File:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.animation import Animation
from kivy.properties import NumericProperty
from random import randint


class MainWindow(Screen):
    pass

class SecondWindow(Screen):
    pass

class ThirdWindow(Screen):
    pass

class WindowManager(ScreenManager):
    pass

class PleaseWork(App):
    a = NumericProperty(0)
    b = NumericProperty(0)
    run_t= 15
    min = 3
    max = 7

    def start(self):
        self.a = randint(self.min, self.max)
        self.anim = Animation(a=0, duration=self.a)
        if self.run_t - self.b <= self.max:
            self.a = self.run_t - self.b
            print("a=",self.a,"b=",self.b)
            self.anim = Animation(a=0, duration = self.a)
        else:
            print(self.run_t - self.b)
            self.anim.bind(on_complete = self.start)
        print('starting anim number:', self.lap_counter)
        self.anim.start(self)

    def count_up(self):
        self.anim = Animation(b = self.run_t, duration = self.run_t)
        self.anim.bind(on_complete = self.finish_callback)
        self.anim.start(self)

    def finish_callback(self, animation, param):
        print('in finish_callback')
        end_1 = self.ids['count_down']
        end_1.text = 'Finished'
        Animation.cancel_all(self)


kv = Builder.load_file("integrate.kv")

class PageScrollerApp(App): 
    def build(self): 
        return kv

if __name__ == "__main__":
    PageScrollerApp().run()

kv file:

WindowManager:
    MainWindow:
    SecondWindow:
    ThirdWindow:


<MainWindow>:
    name: "home"

    FloatLayout:
        Button:
            pos_hint: {"x":0.4, "y":0.05}
            text: "Go!"
            on_release:
                app.root.current = 'low'


<SecondWindow>:
    name: 'low'

    FloatLayout:
        Label:
            id: count_down1
            text: str(round(root.a, 1))
            pos_hint: {"x": 0.4, "y": 0.55}
        Button:
            background_color: 0.5,0.1,1,1
            text: 'next'
            pos_hint: {"x":0.4, "y":0.05}
            on_release:
                app.root.current = "medium"

<ThirdWindow>:
    name: "medium"

    FloatLayout:
        Label:
            id: count_down2
            text: str(round(root.a, 1))
            pos_hint: {"x": 0.4, "y": 0.55}
        Button:
            background_color: 0.5,0.1,1,1
            text: 'Cancel'
            pos_hint: {"x":0.4, "y":0.05}
            on_release:
                app.root.current = "home"

<Button>
    font_size: 20
    color:1,0.2,0.5,1
    size_hint: 0.2, 0.1
    background_color: 0.5,0.8,0.2,1

<Label>
    font_size: 20
    color:1,0.2,0.5,1
    size_hint: 0.2, 0.1
    background_color: 0.5,0.2,0.9,1

В настоящее время, если я пытаюсь запустить программу, появляется следующее сообщение об ошибке:

AttributeError: объект 'SecondWindow' не имеет атрибута'a'

Но я также понимаю, что на самом деле я не вызываю функции внутри класса PleaseWork (App) в любой момент.Я просто не смог разобраться как.Извините, если ответ очевиден, но я новичок в использовании kivy!

1 Ответ

1 голос
/ 05 июля 2019

Проблема - ошибка атрибута 'a'

AttributeError: у объекта 'SecondWindow' нет атрибута 'a'

первопричина

Атрибут класса a определен только в классе PleaseWork(), и этот класс не является корневым. Корень class WindowManager().

Другие проблемы

  • Определены два класса приложения
  • Отсутствующий атрибут, self.lap_counter
  • Отсутствует кв id: count_down в self.ids['count_down']

Решение

Следующие улучшения необходимы для файлов py и kv.

py файл

  • Удалить pass из class WindowManager() и заголовок класса, class PleaseWork(App)
  • Реализуйте метод reset() для сброса a и b в ноль
  • Добавить *args в качестве аргументов в методе start()

Snippets - py file

class WindowManager(ScreenManager):
    a = NumericProperty(0)
    b = NumericProperty(0)
    run_t = 15
    min = 3
    max = 7

    def reset(self):
        self.a = 0
        self.b = 0

    def start(self, *args):
        self.a = randint(self.min, self.max)
        self.anim = Animation(a=0, duration=self.a)
        if self.run_t - self.b <= self.max:
            self.a = self.run_t - self.b
            print("a=", self.a, "b=", self.b)
            self.anim = Animation(a=0, duration=self.a)
        else:
            print(self.run_t - self.b)
            self.anim.bind(on_complete=self.start)
        # print('starting anim number:', self.lap_counter)
        self.anim.start(self)

    def count_up(self):
        self.anim = Animation(b=self.run_t, duration=self.run_t)
        self.anim.bind(on_complete=self.finish_callback)
        self.anim.start(self)

    def finish_callback(self, animation, param):
        print('in finish_callback')
        end_1 = self.ids['count_down']
        end_1.text = 'Finished'
        Animation.cancel_all(self)


class PageScrollerApp(App):
    def build(self):
        return Builder.load_file("integrate.kv")

файл кв

  • Методы вызова reset() и start() в on_release событии кнопки «Перейти»
  • Заменить все вхождения root.a на root.manager.a

Фрагменты - файл kv

<MainWindow>:
    name: "home"

    FloatLayout:
        Button:
            pos_hint: {"x":0.4, "y":0.05}
            text: "Go!"
            on_release:
                root.manager.reset()
                root.manager.start()
                root.manager.current = 'low'

<SecondWindow>:
    name: 'low'

    FloatLayout:
        Label:
            id: count_down1
            text: str(round(root.manager.timer.a, 1))
            pos_hint: {"x": 0.4, "y": 0.55}
        Button:
            background_color: 0.5,0.1,1,1
            text: 'next'
            pos_hint: {"x":0.4, "y":0.05}
            on_release:
                root.manager.current = "medium"

<ThirdWindow>:
    name: "medium"

    FloatLayout:
        Label:
            id: count_down2
            text: str(round(root.manager.timer.a, 1))
            pos_hint: {"x": 0.4, "y": 0.55}
        Button:
            background_color: 0.5,0.1,1,1
            text: 'Cancel'
            pos_hint: {"x":0.4, "y":0.05}
            on_release:
                root.manager.current = "home"

выход

SecondWindow ThirdWindow

...