首页 > 解决方案 > 在屏幕之间传递值

问题描述

我对kivy完全陌生。该应用程序有两个屏幕 - CalculateScreen 和 ResultScreen。ScreenManager 提供屏幕之间的切换。CalculateScreen 从 TextInput 中获取五个值:start_distance、finish_distance、start_gasoline、added_fuel、normal_consumption。方法计数返回三个值 - day_distance、daily_consumption、gases_left ,必须在按下“计算”按钮时将其传递给 ResultScreen 的适当文本标签: day_distance_result、daily_consumption_result、gass_after_result。我试图通过在更改屏幕时调用 set_values 方法来做到这一点,但它不能以适当的方式工作:

Traceback (most recent call last):
   File "mainlogic.py", line 105, in <module>
     MyApp().run()
   File "C:\Users\Anna\project\lib\site-packages\kivy\app.py", line 950, in run
     runTouchApp()
   File "C:\Users\Anna\project\lib\site-packages\kivy\base.py", line 582, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\Anna\project\lib\site-packages\kivy\base.py", line 347, in mainloop
     self.idle()
   File "C:\Users\Anna\project\lib\site-packages\kivy\base.py", line 391, in idle
     self.dispatch_input()
   File "C:\Users\Anna\project\lib\site-packages\kivy\base.py", line 342, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\Anna\project\lib\site-packages\kivy\base.py", line 248, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\Anna\project\lib\site-packages\kivy\core\window\__init__.py", line 1412, in on_motion
     self.dispatch('on_touch_down', me)
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\Anna\project\lib\site-packages\kivy\core\window\__init__.py", line 1428, in on_touch_down
     if w.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\Anna\project\lib\site-packages\kivy\uix\screenmanager.py", line 1198, in on_touch_down
     return super(ScreenManager, self).on_touch_down(touch)
   File "C:\Users\Anna\project\lib\site-packages\kivy\uix\widget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\Anna\project\lib\site-packages\kivy\uix\relativelayout.py", line 297, in on_touch_down
     ret = super(RelativeLayout, self).on_touch_down(touch)
   File "C:\Users\Anna\project\lib\site-packages\kivy\uix\widget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\Anna\project\lib\site-packages\kivy\uix\widget.py", line 545, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 709, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\Anna\project\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
   File "C:\Users\Anna\project\lib\site-packages\kivy\lang\builder.py", line 57, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\Anna\project\kivy-project\my.kv", line 72, in <module>
     on_press: root.set_values()
   File "mainlogic.py", line 55, in set_values
     result_screen.ids.day_distance_result.text = self.day_distance
 AttributeError: 'CalculateScreen' object has no attribute 'day_distance'

这是我的main.py文件。

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, StringProperty


class CalculateScreen(Screen):
    start_distance = ObjectProperty()
    finish_distance = ObjectProperty()
    start_gasoline = ObjectProperty()
    added_fuel = ObjectProperty()
    normal_consumption = ObjectProperty()
    
    def counting(self, start_distance, finish_distance, start_gasoline, added_fuel, normal_consumption):
        if self.added_fuel == 0:
            day_distance = str(finish_distance-start_distance)
            daily_consumption = str((int(day_distance)*normal_consumption)/100)
            gasoline_left = str(start_gasoline-float(daily_consumption))
        else:
            day_distance = str(finish_distance-start_distance) 
            daily_consumption = str((float(day_distance)*normal_consumption)/100)
            gasoline_left = str((start_gasoline+added_fuel)-float(daily_consumption))
        return day_distance, daily_consumption, gasoline_left
        
    def calculations(self):
        try:
            start_distance = float(self.start_distance.text)
            finish_distance = float(self.finish_distance.text)
            start_gasoline = float(self.start_gasoline.text)
            added_fuel = float(self.added_fuel.text)
            normal_consumption = float(self.normal_consumption.text)
        except:
            start_distance = 0
            finish_distance = 0
            start_gasoline = 0
            added_fuel = 0
            normal_consumption = 0
        
            self.counting(start_distance, finish_distance, start_gasoline, added_fuel, normal_consumption)
    
    def set_values(self):
        result_screen = self.manager.get_screen("result")
        result_screen.ids.day_distance_result.text = self.day_distance
        result_screen.daily_consumption_result.text = self.daily_consumption
        result_screen.gasoline_after_result.text = self.gasoline_left
        
        
class ResultScreen(Screen):
    day_distance_result = ObjectProperty()
    daily_consumption_result = ObjectProperty()
    gasoline_after_result = ObjectProperty()
    

class Manager(ScreenManager):
    screen_one = ObjectProperty(None)
    screen_two = ObjectProperty(None)
    

class MyApp(App):
    def build(self):
        m = Manager()
        return m

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

这是我的my.kv文件。

<Manager>:
    id: screen_manager
    screen_one: screen_one
    screen_two: screen_two
    
    CalculateScreen:
        id: screen_one
        name: "calculator"
        manager: screen_manager
    
    ResultScreen:
        id: screen_two
        name: "result"
        manager: screen_manager
        
        
<CalculateScreen>
    name: "calculator"

    start_distance: start_distance
    finish_distance: finish_distance
    start_gasoline: start_gasoline
    added_fuel: added_fuel
    normal_consumption: normal_consumption
    
    BoxLayout:
        orientation: 'vertical'
        padding: 20
        spacing: 10
        
        BoxLayout:
            orientation: 'vertical'
            Label:
                text: "Start distance"
            TextInput:
                id: start_distance
        
        BoxLayout:
            orientation: 'vertical'
            Label:
                text: "Final distance"
            TextInput:
                id: finish_distance
        
        BoxLayout:
            orientation: 'vertical'
            Label:
                text: "Fuel before leaving"
            TextInput:
                id: start_gasoline
        
        BoxLayout:
            orientation: 'vertical'
            Label:
                text: "Refuelling"
            TextInput:
                id: added_fuel
        
        BoxLayout:
            orientation: 'vertical'
            Label:
                text: "Normal consumption"
            TextInput:
                id: normal_consumption
    
        Button:
            text:'Calculate'
            on_press: root.calculations()
            on_press: root.set_values()
            on_release: root.manager.current = "result"
        
                            
<ResultScreen>
    name: "result"
    
    on_enter: root.manager.get_screen("calculator").set_values()
    
    day_distance_result: day_distance_result
    daily_consumption_result: daily_consumption_result
    gasoline_after_result: gasoline_after_result
    
    
    BoxLayout:
        orientation: 'vertical'
        padding: 20
        spacing: 10
    
        BoxLayout:
            Label
                text: "Daily distance result"
            Label:
                text: "0"
                id: day_distance_result
        
        BoxLayout: 
            Label
                text: "Daily consumption result"
            Label:
                text: "0"
                id: daily_consumption_result
    
        BoxLayout:
            Label
                text: "Gasoline after"
            Label:
                text: "0"
                id: gasoline_after_result
        
        
        BoxLayout:
            orientation: 'horizontal'
            spacing: 10
        
            Button:
                text: 'Exit'
            Button:
                text: 'Recalculate'
                on_release: root.manager.current = "calculator"
        

标签: pythonkivy

解决方案


由于您的set_values()方法引用了CalculateScreen实例的属性(如self.day_distanceself.daily_consumption等),因此您必须提供这些属性。您可以通过修改您的counting()方法来设置这些属性来做到这一点:

def counting(self, start_distance, finish_distance, start_gasoline, added_fuel, normal_consumption):
    if self.added_fuel == 0:
        self.day_distance = str(finish_distance - start_distance)
        self.daily_consumption = str((int(self.day_distance) * normal_consumption) / 100)
        self.gasoline_left = str(start_gasoline - float(self.daily_consumption))
    else:
        self.day_distance = str(finish_distance - start_distance)
        self.daily_consumption = str((float(self.day_distance) * normal_consumption) / 100)
        self.gasoline_left = str((start_gasoline + added_fuel) - float(self.daily_consumption))
    # return self.day_distance, self.daily_consumption, self.gasoline_left

请注意,由于未使用返回值,因此可以删除该行。

除非出现异常,否则您的calculations()方法不会调用该方法。counting()可能只是一个错字。调用counting()应该是不缩进的:

def calculations(self):
    try:
        start_distance = float(self.start_distance.text)
        finish_distance = float(self.finish_distance.text)
        start_gasoline = float(self.start_gasoline.text)
        added_fuel = float(self.added_fuel.text)
        normal_consumption = float(self.normal_consumption.text)
    except:
        start_distance = 0
        finish_distance = 0
        start_gasoline = 0
        added_fuel = 0
        normal_consumption = 0

    self.counting(start_distance, finish_distance, start_gasoline, added_fuel, normal_consumption)

另一个问题是文件中Button的on_press属性。与任何人所期望的完全相反,构造:Calculatekv

    Button:
        text:'Calculate'
        on_press: root.calculations()
        on_press: root.set_values()
        on_release: root.manager.current = "result"

结果是root.set_values()先调用,然后root.calculations()调用第二。解决方法是只使用一个on_press属性:

        text:'Calculate'
        on_press:
            root.calculations()
            root.set_values()
        on_release: root.manager.current = "result"

推荐阅读