Значение из файла py в файл kv. Использование примера витрины

Я хочу передать значение из таймера в моем main.py в ProgressBar в файле exit.kv, но используя файловую структуру, подобную демонстрационному примеру. Я пытаюсь сделать кнопку с таймером, чтобы программа не вышла случайно, мне нужно было бы удерживать кнопку в течение нескольких секунд.

Перепробовал много вещей, но я не могу найти решение.

Проекту необходимо передать больше значений, прочитанных в main.py (используя ЦАП на моем Raspberry pi), в несколько разных файлов .kv.

Это мой первый проект Kivy, но также и мой первый проект Python, поэтому кривая обучения для меня крутая.


ИЗМЕНИТЬ:

Что мне нужно, так это передать значение (exit_time) в файле main.py в ProgressBar (exit_bar) в файле exit.kv, чтобы показать, как долго я необходимо нажать кнопку (exit_button) перед выходом из программы.

когда программа запускается, консоль python выполняет обратный отсчет, но я не могу показать его в ProgressBar (или метках или чем-то еще в файле exit.kv.

Как узнать, нужно ли мне использовать app. или корень. или screen.ids.exit_bar.value или как?


РЕДАКТИРОВАНИЕ еще раз: решение

Я удалил в main.py все, что касается таймера, и поместил это в main.py;

#
#   The Exit Timer, counting up to 20 from 0 before exiting.
#   If Press button start Timer. If button up, reset timer
#

    def my_callback(self, dt):
        global exit_time
        exit_time += 1
        if exit_time == 101:
            sys.exit("piMote stopped!")
        self.time = exit_time

    def start_exit_timer(self):
        Clock.schedule_interval(self.my_callback, 0.01)

    def stop_exit_timer(self):
        global exit_time
        Clock.unschedule(self.my_callback)
        Clock.schedule_once(self.my_callback,0)
        exit_time = -1

А затем я изменил часть файла exit.ky на

   ProgressBar:
        id: exit_bar
        max: 100
        value: app.time
        size_hint_x: .3
        size_hint_y: None
        height: '10dp'

На самом деле все, что мне нужно было сделать, это добавить self.time = exit_time"


main.py

from time import time
from kivy.app import App
from os.path import dirname, join
from kivy.lang import Builder
from kivy.properties import NumericProperty, StringProperty, BooleanProperty,\
    ListProperty
from kivy.clock import Clock
from kivy.uix.screenmanager import Screen
from kivy.uix.checkbox import CheckBox
import os
import sys
from kivy.config import Config


exit_time = 0
timer_start = 0

class ShowcaseScreen(Screen):
    fullscreen = BooleanProperty(False)
    def add_widget(self, *args):
        if 'content' in self.ids:
            return self.ids.content.add_widget(*args)
        return super(ShowcaseScreen, self).add_widget(*args)

class ShowcaseApp(App):
    index = NumericProperty(-1)
    current_title = StringProperty()
    time = NumericProperty(0)
    screen_names = ListProperty([])
    hierarchy = ListProperty([])
    exit_time = NumericProperty(21)

    def build(self):
        self.title = 'hello world'
        self.screens = {}
        self.available_screens = [
            'Exit']
        self.screen_names = self.available_screens
        curdir = dirname(__file__)
        self.available_screens = [join(curdir, 
            '{}.kv'.format(fn)) for fn in self.available_screens]
        screen = self.load_screen(self.index +1)
        self.current_title = screen.name

#
#   choose the right screen from spinner
#

    def on_current_title(self, instance, value):
        self.root.ids.spnr.text = value

    def go_screen(self, idx):

        print self.index
        self.index = idx
        self.root.ids.sm.switch_to(self.load_screen(idx), direction='left')

    def load_screen(self, index):
        if index in self.screens:
            return self.screens[index]
        screen = Builder.load_file(self.available_screens[index].lower())
        self.screens[index] = screen
        return screen

#
#   timer start for joystick and exit timer
#

    def __init__(self,**kwargs):
        super(ShowcaseApp,self).__init__(**kwargs)
        Clock.schedule_interval(self.my_timer, 0.1)

#
#   The Exit Timer, counting up to 20 from 0 before exiting.
#   If Press button start Timer. If button up, reset timer
#

    def my_timer(screen, dt):
        if timer_start == 1:
            global exit_time
            exit_time += 1
            if exit_time == 21:
                sys.exit("piMote stopped!")
            print exit_time
            return exit_time  + 7
        #################################################################
        #   Need to do something here to make the timer-progressbar     #
        #   move, counting how long the button is pressed               #
        #################################################################

    def start_exit_timer(self):
        global timer_start
        timer_start = 1

    def stop_exit_timer(self):
        global timer_start, exit_time
        exit_time = 0
        timer_start = 0

if __name__ == '__main__':
    ShowcaseApp().run()

витрина.кв

#:kivy 1.8.0
#:import Factory kivy.factory.Factory

<ActionSpinnerOptions@SpinnerOption>
    background_color: .4, .4, .4, 1

<ActionSpinner@Spinner+ActionItem>
    canvas.before:
        Color:
            rgba: 0.128, 0.128, 0.128, 1
        Rectangle:
            size: self.size
            pos: self.pos
    border: 27, 20, 12, 12
    #background_normal: 'atlas://data/images/defaulttheme/action_group'
    option_cls: Factory.ActionSpinnerOptions

<ShowcaseScreen>:
    ScrollView:
        do_scroll_x: False
        do_scroll_y: False if root.fullscreen else (content.height > root.height - dp(16))
        AnchorLayout:
            size_hint_y: None
            height: root.height if root.fullscreen else max(root.height, content.height)
            GridLayout:
                id: content
                cols: 1
                spacing: '8dp'
                padding: '8dp'
                size_hint: (1, 1) if root.fullscreen else (.8, None)
                height: self.height if root.fullscreen else self.minimum_height

BoxLayout:
    orientation: 'vertical'

    canvas.before:
        Color:
            rgb: .6, .6, .6
        Rectangle:
            size: self.size
            #source: 'data/background.png'

    ActionBar:

        ActionView:
            id: av
            ActionPrevious:
                title: 'piMote'

            ActionSpinner:
                id: spnr
                important: True
                text: 'Jump to Screen'
                values: app.screen_names
                on_text:
                    if sm.current != args[1]:\
                    idx = app.screen_names.index(args[1]);\
                    app.go_screen(idx)

    ScreenManager:
        id: sm
        on_current_screen:
            spnr.text = args[1].name
            idx = app.screen_names.index(args[1].name)
            if idx > -1: app.hierarchy.append(idx)

выход.кв

ShowcaseScreen:
    name: 'Exit'

    Label:
        id: exit_label1
        text: "Are you really sure\n you want to quit?"
        size_hint_y: None
        height: '36dp'

    ProgressBar:
        id: exit_bar
        max: 20
        #value: app.my_timer()
        size_hint_x: .3
        size_hint_y: None
        height: '10dp'

    Button:
        id: exit_button
        text: "Yes"
        size_hint_x: .2
        size_hint_y: None
        height: '48dp'
        on_press: app.start_exit_timer()
        on_release: app.stop_exit_timer()

person PunyViking    schedule 31.12.2016    source источник
comment
TL;TR: Не могли бы вы упростить свой пример. Опубликуйте свою трассировку стека.   -  person Laurent LAPORTE    schedule 31.12.2016
comment
Я не знаю, как упростить мой пример и заставить его работать как надо. Если я отрежу от него больше, он не будет работать так, как задумано.   -  person PunyViking    schedule 31.12.2016
comment
Я не знаю, что такое трассировка стека, поэтому не могу опубликовать... Извините!   -  person PunyViking    schedule 31.12.2016


Ответы (1)


Ваше решение слишком сложное... вы можете просто измерить время, прошедшее с момента прессы, а затем принять решение уйти.

#forget about all the timers code...
import time #gonna need this
EXIT_BUTTON_TIME = 2.0 # 2 seconds is OK?
...

    def exit_button_pressed(self):
        self.exit_pressed = time.time()


    def exit_button_release(self):
        if time.time() - self.exit_pressed >  EXIT_BUTTON_TIME:
            exit() # or something else you want to do

Также измените имена функций в файле KV...

    ...
    on_press: app.exit_button_pressed()
    on_release: app.exit_button_release()

Я не говорю, что ваш подход не может работать, но он более сложен (импортировать это)

person Yoav Glazner    schedule 31.12.2016
comment
Спасибо, я уже думал об этом решении. Проблема с вашим решением на самом деле не проблема, но мне нужно иметь возможность передавать другие значения в другие файлы kv позже в этом проекте. Я делаю пульт дистанционного управления для своих роботов, и мне нужно иметь возможность считывать положение джойстиков и отображать значения на экране kv. - person PunyViking; 01.01.2017
comment
@PunyViking - вам придется написать еще один более краткий вопрос о передаче параметров, поскольку приведенный выше вопрос недостаточно ясен. - person Yoav Glazner; 01.01.2017