0

I just started developing my first app in python using kivy. I generated the general layout of the app and also some logic in an python file in addition to my main py to seperate everything a bit. This worked perfectly fine and the app was running without any issues. I wanted to add some screens when hitting buttons that provide extra information. Managed to do so, but now the app crashes when hitting the buttons that worked before adding the extra screens. Those buttons use classes that aren't implemented in the main.py but in a side file. Like I explained, they worked before adding the ScreenManager. here's the short version of the error I get: AttributeError: 'super' object has no attribute '__getattr__'

Main.py: peenomat.py

import kivy
# -*- coding: iso-8859-1 -*-
from kivy.app import App

from kivy.uix.button import Label
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.core.text import LabelBase
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.properties import ObjectProperty
from kivy.config import Config


Builder.load_file('Header.kv')
Builder.load_file('Statusbar.kv')
Builder.load_file('Inputparameters.kv')
Builder.load_file('Outputparameters.kv')
Builder.load_file('Extra.kv')
#loading main kv
Builder.load_file('peenomat.kv')


class Peenomat(Screen):
    pass


class Instruction(Screen):
    pass

class Additional(Screen):
    pass

# Create the screen manager
sm = ScreenManager()
sm.add_widget(Peenomat(name='peenomat'))
sm.add_widget(Instruction(name='instruction'))
sm.add_widget(Additional(name='additional'))


class PeenomatApp(App):
    def build(self):
        self.icon = 'icon.png'
        #return pm
        return sm
        #return Peenomat()

if __name__=="__main__":

    PeenomatApp().run()

the main kv.file: peenomat.kv

<Peenomat>

    AnchorLayout:
        anchor_x: 'left'
        anchor_y: 'bottom'
        GridLayout:
            cols: 1
 
            InputParameters:
                id:_input_parameters

            StatusBar:
                id:_status_bar
                       
                

<Instruction>:
    AnchorLayout:
        anchor_x: 'left'
        anchor_y: 'bottom'
        GridLayout:
            cols: 1
            canvas.before:
            Label:
                text:

            Button:
                text: 
                on_release:
                    app.root.current = "peenomat"
                    app.root.transition.direction = "up"

<Additional>:
    AnchorLayout:
        anchor_x: 'left'
        anchor_y: 'bottom'
        GridLayout:
            cols: 1
            Button:
                text: 
                on_release:
                    app.root.current = "peenomat"
                    app.root.transition.direction = "left"

the .kv file where I reference the function of the buttons: statusbar.kv

#: import statusbar StatusBar

<StatusBar@BoxLayout>

    orientation:'horizontal'
    padding:
    spacing: 

    Label:
        size_hint: 0.05, 1

    Button:
        text: 'Leeren'
        on_press: root.btn_clear()

    Button:
        text: "Mehr"
        on_release:
            app.root.current = "additional"
            app.root.transition.direction ="right"


    Button:
        text: u"Los schl\u00e4gts"
        on_press: root.btn_submit()

    Button:
        text: "?"
        on_release:
            app.root.current = "instruction"
            app.root.transition.direction ="down"

and finally the python file that provides the classes where i generate the functions of the buttons that now crash: StatusBAr.py

from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivy.app import App
from kivy.lang import Builder
#from Inputparameters import InputParameters


ver = ''
class InputParameters(GridLayout):
    verfahren =ObjectProperty(None)

    def on_state(self, togglebutton):
        tb = togglebutton
        global ver
        if tb.state == 'down':
            self.verfahren = tb.text
            ver = tb.text
            print(self.verfahren, ver)
            return self.verfahren


class StatusBar(BoxLayout):
    #InputGrößen
    group_mode = False
    prozess = ObjectProperty(None)
    vorbehandlung = ObjectProperty(None)
    material = ObjectProperty(None)
    haerte = ObjectProperty(None)
    rauheit = ObjectProperty(None)
    verfahren = ObjectProperty(None)

    #OutputGrößen
    frequency = StringProperty(None)
    speed = StringProperty(None)
    hub = StringProperty(None)

    def btn_submit(self):
        global ver
        ip = App.get_running_app().root.ids._input_parameters
        op = App.get_running_app().root.ids._output_parameters

        frequenz = 0
        if ip.haerte.value < 50:
            op.frequency = str(180) +" Hz"
            op.speed = str(2.4) +" mm/s"
            op.hub = str(3.4) + " mm"
        elif ip.haerte.value < 60:
            op.frequency = str(200) +" Hz"
            op.speed = str(3.5) + " mm/s"
            op.hub = str(5.23) + " mm"
        else:
            op.frequency = str(220) +" Hz"
            op.speed = str(1.2) + " mm/s"
            op.hub = str(7.2) + " mm"
        #control to see if right value is taken
        print(op.frequency)

    def btn_clear(self):
        ip = App.get_running_app().root.ids._input_parameters
        op = App.get_running_app().root.ids._output_parameters
        ip.pro1.state = "normal"
        ip.pro2.state = "normal"
        ip.pro3.state = "normal"
        ip.material.text = "Auswahl treffen"
        ip.vorbehandlung.text = "Auswahl treffen"
        ip.haerte.value = 55
        ip.rauheit.value = 5.5
        op.frequency = "---"
        op.speed = "---"
        op.hub = "---"

so if the buttons submit or clear are used I get the following error:

[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "kivy\properties.pyx", line 860, in kivy.properties.ObservableDict.__getattr__
 KeyError: '_input_parameters'
 
 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:/Users/schum/Dokumente/TUD/Masterthesis/Peenomat.py", line 79, in <module>
     PeenomatApp().run()
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\app.py", line 855, in run
     runTouchApp()
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\base.py", line 504, in runTouchApp
     EventLoop.window.mainloop()
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\core\window\window_sdl2.py", line 747, in mainloop
     self._mainloop()
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\core\window\window_sdl2.py", line 479, in _mainloop
     EventLoop.idle()
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\base.py", line 342, in idle
     self.dispatch_input()
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\base.py", line 327, in dispatch_input
     post_dispatch_input(*pop(0))
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\base.py", line 233, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\core\window\__init__.py", line 1402, in on_motion
     self.dispatch('on_touch_down', me)
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\core\window\__init__.py", line 1418, in on_touch_down
     if w.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\screenmanager.py", line 1191, in on_touch_down
     return super(ScreenManager, self).on_touch_down(touch)
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\widget.py", line 549, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\relativelayout.py", line 288, in on_touch_down
     ret = super(RelativeLayout, self).on_touch_down(touch)
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\widget.py", line 549, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\widget.py", line 549, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\widget.py", line 549, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\widget.py", line 549, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\uix\behaviors\button.py", line 151, in on_touch_down
     self.dispatch('on_press')
   File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\venv\lib\site-packages\kivy\lang\builder.py", line 64, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\Statusbar.kv", line 38, in <module>
     on_press: root.btn_submit()
   File "C:\Users\schum\Dokumente\TUD\Masterthesis\StatusBar.py", line 41, in btn_submit
     ip = App.get_running_app().root.ids._input_parameters
   File "kivy\properties.pyx", line 863, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'

the function of the buttons is to get selected parameter out of this .kv.file

inputparameters.kv

#: import statusbar StatusBar

<InputParameters@GridLayout>
    #Initialisierung .py zu .kv Ids
    prozess: _prozess
    pro1: _prozess1
    pro2: _prozess2
    pro3: _prozess3
    vorbehandlung: _vorbehandlung
    material: _material
    haerte: _haerte
    rauheit: _rauheit

    cols: 2
    padding: 25
    spacing: 10

    #Prozess
    Label:
        text:'Prozess:              '

    BoxLayout:
        orientation: 'horizontal'
        id: _prozess

        ToggleButton:
            id:_prozess1
            text:'P-MOH'
            group: "proc_group"
            on_state: root.on_state(self)

        ToggleButton:
            id:_prozess2
            text:'E-MOH'
            group: "proc_group"
            on_state: root.on_state(self)

        ToggleButton:
            id:_prozess3
            text:'PE-MOH'
            group: "proc_group"
            on_state: root.on_state(self)

    #Material

    Label:
        text: 'Material:'

    Spinner:
        id: _material
        text: "Auswahl treffen"
        values: ['1.2379', 'Gusseisen', 'Kautschuk', 'Carbon', 'Adamantium']

    # Herstellschritte
    Label:
        text:'Fertigungsschritte:'

    Spinner:
        id: _vorbehandlung
        text: "Auswahl treffen"
        values: [u'Fr\u00e4sen', 'Erodieren', 'Schleifen', 'Polieren']

    # Haerte
    Label:
        text: u"H\u00e4rte:"

    BoxLayout:
        orientation: 'vertical'

        Label:
            text: str(_haerte.value) + ' HRC'

        Slider:
            id: _haerte
            min: 45
            max: 65
            step: 1
            value_track: True

    # Rauheit
    Label:
        text:'Rauheit:'              

    BoxLayout:
        orientation: 'vertical'
        Label:
            text: str("%.1f" % _rauheit.value) + ' Rz' #eine Nachkommastelle

        Slider:
            id: _rauheit
            min: 1
            max: 10
            value_track: True

whats weirrd is that the togglebuttons can still use the function generatet in the statusbar.py and do their job. I hope you can help me out with this and don't even know where to start... Thank's in advance!

1 Answers1

1

The ids dictionary is created for each rule in the kv file, and those ids are placed in the dictionary for the root of that rule. So the _input_parameters id is only in the ids of the Peenomat instance.

So, I think you need to change:

    ip = App.get_running_app().root.ids._input_parameters

to something like:

    ip = App.get_running_app().root.get_screen('peenomat').ids._input_parameters

The root of your App is the ScreenManager, and get_screen('peenomat') gets the Peenomat Screen instance.

John Anderson
  • 35,991
  • 4
  • 13
  • 36