【问题标题】:Value from a py file to a kv file. Using the showcase example从 py 文件到 kv 文件的值。使用展示示例
【发布时间】:2016-12-31 17:07:09
【问题描述】:

我想将 main.py 中的计时器中的值传递给 exit.kv 文件中的 ProgressBar,但使用的文件结构类似于展示示例。我正在尝试制作一个定时按钮,这样程序就不会意外退出,我需要按住按钮几秒钟。

尝试了很多东西,但我找不到解决方案。

项目需要将 main.py 中读取的更多值(在我的 Raspberry pi 上使用 DAC)传递给几个不同的 .kv 文件

这是我的第一个 Kivy 项目,也是我的第一个 Python 项目,所以我的学习曲线非常陡峭。


编辑:

我需要将main.py文件中的(exit_time)值传递给exit.kv文件中的ProgressBar(exit_bar)来显示在退出程序之前我需要按下按钮(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()

showcase.kv

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

退出.kv

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

【问题讨论】:

  • TL;TR:你能简化你的例子吗?发布您的堆栈跟踪。
  • 我不知道如何简化我的示例并使其正常工作。如果我再删掉它,它将无法按预期工作。
  • 我不知道堆栈跟踪是什么所以我不能发布它......对不起!

标签: python kivy kivy-language


【解决方案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()

我并不是说你的方法行不通,但它更复杂 (import this)

【讨论】:

  • 谢谢,我已经考虑过这个解决方案。您解决方案的“问题”并不是真正的问题,但我需要能够稍后在该项目中将其他值传递给其他 kv 文件。我正在为我的机器人制作遥控器,我需要能够读取操纵杆的位置并在 kv 屏幕上显示值。
  • @PunyViking - 你必须写另一个关于传递参数的更简洁的问题,因为上面的问题不够清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
相关资源
最近更新 更多