Kivy - FloatLayout 中的定时器集成

Kivy - Timer Integration in FloatLayout

问题很简单,让 Kivy 将 Timer1 代码作为标签集成到 FloatLayout

我有这个 .py 文件:

import kivy

kivy.require('1.10.0')

from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.stacklayout import StackLayout
from kivy.clock import Clock
from kivy.properties import StringProperty, NumericProperty, ObjectProperty
from digitalclock import DigitalClock
from kivy.animation import Animation

import time


class IntroScreen(Screen):
    pass


class ContScreen(Screen):
    pass


class ScreenManagement(ScreenManager):
    pass


backbone = Builder.load_file("main.kv")


class Status(FloatLayout):
    _change = StringProperty()
    _tnd = ObjectProperty(None)

    def update(self, *args):
        self.time = time.asctime()
        self._change = str(self.time)
        self._tnd.text = str(self.time)
        print (self._change)


class Timer1(Label):
    a = NumericProperty(10)  # seconds
    color = 1, 1, 1, 1
    font_size = 50

    def start(self):
        Animation.cancel_all(self)  # stop any current animations
        self.anim = Animation(a=0, duration=self.a)

        def finish_callback(animation, incr_crude_clock):
            incr_crude_clock.text = "COOL"
        self.anim.bind(on_complete=finish_callback)
        self.anim.start(self)

    def on_a(self, instance, value):
        self.text = str(round(value, 1))


class XGApp(App):
    time = StringProperty()

    def update(self, *args):
        self.time = str(time.asctime())

    def build (self):
        Clock.schedule_interval(self.update, 1)
        t1 = Timer1()
        return backbone


xApp = XGApp()

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

和.kv:

<ContScreen>:
    DigitalClock:
        pos_hint: {'center_x': 0.1, 'center_y': 0.9}
        size_hint: (0.075, 0.075)

    StackLayout
        orientation: "tb-rl"
        spacing: 15

        Button:
            text: "1"
            size_hint: None, .16
            width: 225
            on_press:
                self.background_color = (1.7, 0, 1.7, 1)
                t1.start()

我正在尝试将 Timer1 方面作为 .kv 上 FloatLayout 中的标签,它在触发按钮时出现。目前,我得到的是作为全屏标签的 Timer1。

请帮忙!

使其工作的一种方法是让 Button 创建计时器。首先将 start_timer() 方法添加到 ContScreen class:

class ContScreen(Screen):
    def start_timer(self, *args):
        timer = Timer1(size_hint=(0.2, 0.2))
        self.add_widget(timer)
        timer.start()

要使其生效,请进行其他三项更改:

  1. 更改您的 main.kv 文件以制作根小部件(消除 ContScreen 周围的 <>)。
  2. 更改 .kv 文件中按钮的 on_press,将 t1.start() 替换为 root.start_timer()
  3. XGApp class 中的 build 方法中删除 t1 = Timer1() 语句。

另一种方法是在 .kv 文件中创建 Timer1,然后在按下 Button 时启动它 运行。为此,请更改您的 .kv 文件以包含 Timer:

ContScreen:
    DigitalClock:
        pos_hint: {'center_x': 0.1, 'center_y': 0.9}
        size_hint: (0.075, 0.075)

    StackLayout
        orientation: "tb-rl"
        spacing: 15

        Button:
            text: "1"
            size_hint: None, .16
            width: 225
            on_press:
                self.background_color = (1.7, 0, 1.7, 1)
                timer.start()

        Timer1:
            id: timer
            text: '0.0'
            size_hint: (0.2, 0.2)

将您的 backbone = Builder.load_file("main.kv") 移动到 Timer1 class 的定义之后。并将 ContScreen class 改回:

class ContScreen(Screen):
    pass

解决方案

  1. 将定时器标签的设计视图从 Python 代码移动到 kv 文件中。
  2. classTimer添加构造函数并接受参数,root, instance, duration, bg_colour
  3. 在kv文件中,实例化Timer[=38时传递参数root(屏幕'cont')、按钮实例、持续时间、背景颜色 =]
  4. build 方法中,删除 t1 = Timer1()

例子

main.py

import kivy

kivy.require('1.11.0')

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import Clock
from kivy.properties import StringProperty, NumericProperty, ObjectProperty
from kivy.animation import Animation

import time


class IntroScreen(Screen):
    pass


class ContScreen(Screen):
    pass


class ScreenManagement(ScreenManager):
    pass


class Status(FloatLayout):
    _change = StringProperty()
    _tnd = ObjectProperty(None)

    def update(self, *args):
        self.time = time.asctime()
        self._change = str(self.time)
        self._tnd.text = str(self.time)
        print (self._change)


class Timer(Label):
    a = NumericProperty()  # seconds

    def __init__(self, root, instance, duration, bg_colour, **kwargs):
        super(Timer, self).__init__(**kwargs)
        self.obj = instance
        self.a = duration
        self.root = root

        self.obj.disabled = True    # disable widget/button
        self.obj.background_color = bg_colour
        self.root.add_widget(self)  # add Timer/Label widget to screen, 'cont'

    def animation_complete(self, animation, widget):
        self.root.remove_widget(widget)  # remove Timer/Label widget to screen, 'cont'
        self.obj.background_color = [1, 1, 1, 1]    # reset to default colour
        self.obj.disabled = False   # enable widget/button

    def start(self):
        Animation.cancel_all(self)  # stop any current animations
        self.anim = Animation(a=0, duration=self.a)
        self.anim.bind(on_complete=self.animation_complete)
        self.anim.start(self)

    def on_a(self, instance, value):
        self.text = str(round(value, 1))


class XGApp(App):
    time = StringProperty()

    def update(self, *args):
        self.time = str(time.asctime())

    def build (self):
        Clock.schedule_interval(self.update, 1)
        return Builder.load_file("main.kv")


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

kv文件

#:import DigitalClock digitalclock
#:import Timer main.Timer

<ContScreen>:
    DigitalClock:
        pos_hint: {'center_x': 0.1, 'center_y': 0.9}
        size_hint: (0.075, 0.075)

    StackLayout
        orientation: "tb-rl"
        spacing: 15

        Button:
            text: "1"
            size_hint: None, .16
            width: 225
            on_press:
                Timer(root, self, 5, [0.17, 1.7, 0, 1]).start()

        Button:
            text: "2"
            size_hint: None, .16
            width: 225
            on_press:
                Timer(root, self, 10, [1.7, 0, 1.7, 1]).start()


<Timer>:
    canvas.before:
        Color:
            rgba: 0, 0, 0.5, 1  # 50% blue
        Rectangle:
            size: self.size
            pos: self.pos

    size_hint: 0.3, .1
    font_size: 50
    pos_hint: {'center_x': 0.5, 'center_y': 0.5}

输出