Kivy - Интеграция таймера в FloatLayout - PullRequest
0 голосов
/ 22 сентября 2018

Проблема проста: заставить 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 в качестве метки в FloatLayout на .kv, который отображается как кнопкасрабатывает.На данный момент я получил Timer1 как полноэкранный ярлык.

Пожалуйста, помогите!

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Решение

  1. Переместить представление дизайна метки таймера из кода Python в файл kv.
  2. Добавить конструктор для класса Timer и принять аргументы, root, instance, duration, bg_colour
  3. В файле kv передать аргументы root (screen '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 file

#: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}

Выход

Img01 - Button 1 pressed Img02 - Button 2 pressed

0 голосов
/ 24 сентября 2018

Один из способов заставить это работать - заставить Button создать таймер.Начните с добавления метода start_timer() в класс ContScreen:

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. Измените on_press для кнопки в файле .kv, заменив t1.start() на root.start_timer().
  3. Исключите оператор t1 = Timer1() из вашего метода build в классе XGApp.

Другой подход - создать Timer1 в файле .kv и просто запуститьон работает, когда нажата 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.И измените класс ContScreen на:

class ContScreen(Screen):
    pass
...