pythonoopkivykeyerrorkeyword-argument

Python Kivy KeyError with kwargs


I am writing a program to calculate paces for different track events and I am trying to set a variable that represents the event that the user chose to calculate.

Below is the section of the .py file

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

Below is the section of the .kv file

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

The Error message is below:

File "D:\PYTHON PROJECTS\PROJECT 1\Pace Calculator\pacemain.py", line 24, in press if kwargs['event'] == '600': ~~~~~~^^^^^^^^^ KeyError: 'event'

The full .py file is below

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

And finally the full .kv file is below (Note that I am asking specifically about the CalculatorScreenBelowMile and not the 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"

I have tried other ways of setting a variable equal to the event that the user chose, but if you know of another way I would love to hear it because I am new to kivy and fairly new to Python in general and OOP.


Solution

  • One way to solve this is to just save a reference to the event in your CalculatorScreenBelowMile Screen. You can do that by adding an eventpress property in that class:

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

    Then set that property in your press() method:

    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
    

    Then use that saved event in your press_calculate_below() method:

    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]