【问题标题】:Kivy: How to run the same function across several screensKivy:如何在多个屏幕上运行相同的功能
【发布时间】:2019-07-04 23:13:08
【问题描述】:

我正在尝试制作一个计时器,它可以从随机起始数字重复倒计时到零,直到达到预定的时间限制。我已经设法在一个屏幕上执行此操作,但我无法将其适应多个屏幕。

目前,如果我在 PleaseWork(boxLayout) 类中运行函数,它会完全按照应有的方式运行。但是,我想添加一些屏幕,以便主屏幕有一个按钮,上面写着“开始!”并在释放按钮时启动计时器。我希望能够在计时器上的值完全相同的情况下从第二个屏幕循环到第三个屏幕,但我不确定如何执行此操作。

Py 文件:

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 文件:

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 的新手!

【问题讨论】:

    标签: python kivy kivy-language


    【解决方案1】:

    问题 - AttributeError 'a'

    AttributeError: 'SecondWindow' 对象没有属性 'a'

    根本原因

    类属性a只定义在类PleaseWork()中,这个类不是根。根是class WindowManager()

    其他问题

    • 定义了两个应用类
    • 缺少属性,self.lap_counter
    • self.ids['count_down'] 中缺少 kv id: count_down

    解决方案

    py 和 kv 文件中需要以下增强功能。

    py 文件

    • class WindowManager() 和类头class PleaseWork(App) 中删除pass
    • 实现方法reset()ab 重置为零
    • 在方法start() 中添加*args 作为参数

    片段 - py 文件

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

    kv 文件

    • 在“Go”按钮的 on_release 事件中调用方法 reset()start()
    • 将所有出现的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"
    

    输出

    【讨论】:

    • 太好了,谢谢!我完全无法解决这个问题,所以谢谢你,你帮了我很大的忙..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多