Python Kivy 使用kwargs时的KeyError

0 投票
1 回答
19 浏览
提问于 2025-04-14 17:00

我正在写一个程序,用来计算不同田径项目的配速。我想设置一个变量,表示用户选择的要计算的项目。

下面是.py文件的相关部分

class InitialScreen(Screen):

    def press(self, *args, **kwargs):
        if kwargs['event'] == '600':
            eventpress = 'event600'
            App.get_running_app().root.current = 'calculatorbelow_screen'
        if kwargs['event'] == '800':
            eventpress = 'event800'
            App.get_running_app().root.current = 'calculatorbelow_screen'
        return eventpress

下面是.kv文件的相关部分

<InitialScreen>:
    name: "initial"
    GridLayout:
        size: root.width, root.height
        rows:5

        GridLayout:
            cols: 1
            Label:
                text: "Choose your event"
                font_size: 60
                bold: True

        GridLayoutInitial:
            ButtonEventRow1:
                id: event600
                text: "600m"
                on_press: root.press(event='600')

            ButtonEventRow1:
                id: event800
                text: "800m"
                on_press: root.press(event='800')

错误信息如下:

文件 "D:\PYTHON PROJECTS\PROJECT 1\Pace Calculator\pacemain.py",第24行,在press函数中 if kwargs['event'] == '600': ~~~~~~^^^^^^^^^ KeyError: 'event'

完整的.py文件如下

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.graphics import Color, Rectangle
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.properties import ListProperty


kivy.require("2.3.0")
Window.clearcolor = 0, .5, 1, 1


class InitialScreen(Screen):

    def press(self, *args, **kwargs):
        if kwargs['event'] == '600':
            eventpress = 'event600'
            App.get_running_app().root.current = 'calculatorbelow_screen'
        if kwargs['event'] == '800':
            eventpress = 'event800'
            App.get_running_app().root.current = 'calculatorbelow_screen'
        return eventpress


class CalculatorScreenBelowMile(Screen):
    #def __init__(self, **kwargs):
        #super().__init__(**kwargs)

    def press_calculate_below(self, **kwargs):
        splitslist = []
        userevent = InitialScreen().press()
        resultsbelow = self.ids.inputbelow.text
        if userevent == 'event600':
            splitsdividing = [6, 3, 2, 1.5]
        if userevent == 'event800':
            splitsdividing = [8,4,2.67,2]
        if userevent == 'event1000':
            splitsdividing = [10, 5, 3.33, 2.5]
        if userevent == 'event1mile':
            splitsdividing = [16, 8, 5.33, 4]

        for i in splitsdividing:
            results = resultsbelow
            results = int(results)
            results = results / i
            results = int(results)          #removes decimals
            results = str(results)
            splitslist.append(results)
            print(splitslist)
        self.ids.event100split.text = (splitslist[0])
        self.ids.event200split.text = (splitslist[1])
        self.ids.event300split.text = (splitslist[2])
        self.ids.event400split.text = splitslist[3]

    def press_return(self, **kwargs):
        App.get_running_app().root.current = "initial"


class CalculatorScreenAboveMile(Screen):    #Have not started on this yet
    def press(self):
        pass


class WindowManager(ScreenManager):
    pass


kv = Builder.load_file('pacemain.kv')


class MainApp(App):
    def build(self):
        return kv


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

最后,完整的.kv文件如下(注意我特别在问关于CalculatorScreenBelowMile,而不是CalculatorScreenAboveMile)

WindowManager:
    InitialScreen:
    CalculatorScreenBelowMile:
    CalculatorScreenAboveMile:

<ButtonEventRow1@Button>
    background_color: 0,0,1,1
<ButtonEventRow2@Button>
    background_color: 1,0,0,1
<ButtonEventRow3@Button>
    background_color: 0,1,0,1

<GridLayoutInitial@GridLayout>
    cols: 2

<LabelSplits@Label>
    background_color: 0,0,1,1
    canvas.before:
        Color:
            rgba: self.background_color
        Rectangle:
            size: self.size
            pos:self.pos
    size_hint: (.5,.5)
    font_size: 40

#<pressResults@press>:

<Button>:
    font_size: 60

<GridLayout>:
    spacing: 10


<InitialScreen>:
    name: "initial"
    GridLayout:
        size: root.width, root.height
        rows:5

        GridLayout:
            cols: 1
            Label:
                text: "Choose your event"
                font_size: 60
                bold: True

        GridLayoutInitial:
            ButtonEventRow1:
                id: event600
                text: "600m"
                on_press: root.press(event='600')

            ButtonEventRow1:
                id: event800
                text: "800m"
                on_press: root.press(event='800')

        GridLayoutInitial:
            ButtonEventRow2:
                text: "1000m"
                on_press: root.press(event='1000')

            ButtonEventRow2:
                text: "1 Mile"
                on_press: root.press(event='1mile')

        GridLayoutInitial:
            ButtonEventRow3:
                text: "5000m"
                #on_release: app.root.current = "calculatorabove"
            ButtonEventRow3:
                text: "10000m"
                #on_release: app.root.current = "calculatorabove"



<CalculatorScreenBelowMile>:         #Distances of mile and below
    name: "calculatorbelow_screen"
    GridLayout:
        cols:1
        size: root.width, root.height

        GridLayout:         #Top of page
            cols:1
            Label:
                text: "Pace Calculator. Enter your time in seconds."
                font_size: 28
            Label:
                text: "Ex: 120"
                font_size: 50
                bold: True

        GridLayout:     #Enter time and Userinput, calculate and unit
            cols:2
            Label:
                text: "Enter your time here:"
                bold: True
                font_size: 40
                pos_hint_x: .5
                pos_hint_y: .8

            TextInput:
                multiline: False
                id: inputbelow

            Button:
                text: "Calculate"
                on_press: root.press_calculate_below()
            Button:

                text: "Switch unit"
                #ADD SOMETHING HERE

        GridLayout:
            cols: 2

            GridLayout:      #Return bottom right
                cols: 2
                rows: 4
                LabelSplits:
                    text: "100m:"
                LabelSplits:
                    id: event100split
                    text: ""
                LabelSplits:
                    text: "200m:"
                LabelSplits:
                    id: event200split
                    text: ""
                LabelSplits:
                    text: "300m:"
                LabelSplits:
                    id: event300split
                    text: ""
                LabelSplits:
                    text: "400m:"
                LabelSplits:
                    id: event400split
                    text: ""
            GridLayout:
                cols: 1
                Button:
                    text: "Return"
                    on_press: root.press_return()

<CalculatorScreenAboveMile>:         #Distances of above mile
    name: "calculatorabove_screen"
    GridLayout:
        cols:1
        size: root.width, root.height

        GridLayout:         #Top of page
            cols:1
            Label:
                text: "Pace Calculator. Enter your time in seconds."
                font_size: 28
            Label:
                text: "Ex: 120"
                font_size: 50
                bold: True

        GridLayout:     #Enter time and Userinput, calculate and unit
            cols:2
            Label:
                text: "Enter your time here:"
                bold: True
                font_size: 40
                pos_hint_x: .5
                pos_hint_y: .8

            TextInput:
                multiline: False
                id: inputbelow

            Button:
                text: "Calculate"
                on_press: root.press()
                #on_press: app.calculatorbelow()
                #on_press: app.root.current = "resultsabove"
            Button:

                text: "Switch unit"
                #ADD SOMETHING HERE

        GridLayout:
            cols: 2

            GridLayout:      #Return bottom right
                cols: 2
                rows: 4
                LabelSplits:
                    text: "400m:"
                LabelSplits:
                    id: event400split
                    text: ""
                LabelSplits:
                    text: "800m:"
                LabelSplits:
                    id: event800split
                    text: ""
                LabelSplits:
                    text: "1200m:"
                LabelSplits:
                    id: event1200split
                    text: ""
                LabelSplits:
                    text: "1600m:"
                LabelSplits:
                    id: event1600split
                    text: ""
            GridLayout:
                cols: 1
                Button:
                    text: "Return"
                    on_press: app.root.current = "initial"

我尝试过其他方法来设置一个变量,等于用户选择的项目,但如果你知道其他的方法,我很想听听,因为我对kivy还很陌生,对Python和面向对象编程也还不太熟悉。

1 个回答

0

解决这个问题的一种方法是,在你的 CalculatorScreenBelowMile 界面中保存一个事件的引用。你可以通过在这个类里面添加一个 eventpress 属性来实现:

class CalculatorScreenBelowMile(Screen):
    eventpress = StringProperty('')

接着,在你的 press() 方法里设置这个属性:

class InitialScreen(Screen):

    def press(self, *args, **kwargs):
        eventpress = None
        if kwargs['event'] == '600':
            eventpress = 'event600'
            App.get_running_app().root.current = 'calculatorbelow_screen'
        if kwargs['event'] == '800':
            eventpress = 'event800'
            App.get_running_app().root.current = 'calculatorbelow_screen'
        self.manager.get_screen('calculatorbelow_screen').eventpress = eventpress  # set event in the CalculatorScreenBelowMile Screen
        # return eventpress

然后在你的 press_calculate_below() 方法中使用这个保存下来的事件:

def press_calculate_below(self, **kwargs):
    splitslist = []
    # userevent = InitialScreen().press()
    userevent = self.eventpress  # use saved event
    resultsbelow = self.ids.inputbelow.text
    if userevent == 'event600':
        splitsdividing = [6, 3, 2, 1.5]
    if userevent == 'event800':
        splitsdividing = [8,4,2.67,2]
    if userevent == 'event1000':
        splitsdividing = [10, 5, 3.33, 2.5]
    if userevent == 'event1mile':
        splitsdividing = [16, 8, 5.33, 4]

撰写回答