Search code examples
pythonfunctionkivylabelupdating

Kivy updating label when using function via button fails


I'm trying to build an App thats uses certain input Parameters and when hitting a submit button it uses a logic to generate output paramters. I managed to build the app and the input and the triggering via a submit button. Now i want to generate the output, for beginning with an easy logic. I looked up several similar solutions, but somehow they don't work for me. For some reason my .kv file doen't get the updated value for the label text with the error: "ValueError: Label.text accept only str" Eventough everything is declared as a string in the .py. If i change it in the kv to str("...") I get some code line which i guess is the intern id of the attribute but not the assigned value i want to get. I hope you can help. Pls don't be too harsh, I#M new to python and kivy...

main .py, shuldn't be part of the problem Peenomat.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.core.text import LabelBase


Builder.load_file('Statusbar.kv')
Builder.load_file('Inputparameters.kv')
Builder.load_file('Outputparameters.kv')


#Layout
class Peenomat(AnchorLayout):
    pass

class PeenomatApp(App):
    def build(self):
        return Peenomat()

if __name__=="__main__":

    PeenomatApp().run()

.py with the classes and methods for the logic 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




class InputParameters(GridLayout):

    verfahren = ObjectProperty(None)

    def on_state(self, togglebutton):
        tb = togglebutton
        if tb.state == 'down':
            self.verfahren = tb.text
            self.verfahren = tb.text
            print(self.verfahren)
            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)

    #OutputGrößen
    frequenz = StringProperty(None)

    def btn_submit(self):

        ip = App.get_running_app().root.ids._input_parameters
        print("Haerte:", ip.haerte.value, "Rauheit:", ip.rauheit.value, "Material:", ip.material.text, "Vorbehandlung:", ip.vorbehandlung.text)


        if ip.haerte.value < 50:
            self.frequency = str(180)
        elif ip.haerte.value < 60:
            self.frequency = str(200)
        else:
            self.frequency = str(220)
        #control to see if right value is taken
        print(self.frequency, "Hz")

    def btn_clear(self):
        np = App.get_running_app().root.ids._input_parameters
        np.pro1.state = "normal"
        np.pro2.state = "normal"
        np.pro3.state = "normal"
        np.material.text = "Auswahl treffen"
        np.haerte.value = 55
        np.rauheit.value = 5.5

the .kv file that can't get the label text: outputparameters.kv

#: import statusbar StatusBar

<OutputParameters@GridLayout>

    #Initialisierung .py zu .kv
    frequenz: _frequenz

    Label:
        text:'Frequenz:'
        font_size:

    Label:
        id: _frequenz
        text:  root.frequenz
        font_size: 20
     

the .kv file with the submit button, shouldn't be part of the problem either, worked perfectly fine before implementing the part ehre i try to update the text statusbar.kv

#: import statusbar StatusBar

<StatusBar@BoxLayout>

    orientation:'horizontal'

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

    Button:
        text: 'Submit'
        on_press: root.btn_submit()

the file where i put in all the inputparameters, rather important: 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


    #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: ""
        values: 

    # Herstellschritte
    Label:
        text:'Fertigungsschritte:'

    Spinner:
        id: _vorbehandlung
        text: 
        values: 

    # Haerte
    Label:
        text:'Haerte:'

    BoxLayout:
        orientation: 'vertical'

        Label:
            text: str(_haerte.value) 

        Slider:
            id: _haerte

    # Rauheit
    Label:
        text:'Rauheit:             

    BoxLayout:
        orientation: 'vertical'

        Label:
            text: 

        Slider:
            id: _rauheit

and the file where my layout is embedded (also rather necessary) peenomat.kv

<Peenomat>

    AnchorLayout:
        anchor_x: 'left'
        anchor_y: 'bottom'
        GridLayout:
            cols: 1

            canvas.before:
                Color:
                Rectangle:
                    pos: self.pos
                    size: self.size

            InputParameters:
                id:_input_parameters

            StatusBar:
                id:_status_bar

            OutputParameters:
                id:_output_parameters


I really hope you can help, have been struggeling with this for a while and it should rather be easy...thanks in advance!


Solution

  • In your kv rule for <OutputParameters@GridLayout> you have a line:

    frequenz: _frequenz
    

    which sets frequenz to be a reference to the Label with the id of _frequenz. Then in that Label you are setting text using:

    text:  root.frequenz
    

    So, you are trying to set the text of the Label to a reference to that Label

    I suggest trying something like this:

    <OutputParameters@GridLayout>
    
        #Initialisierung .py zu .kv
        frequenz: _frequenz
        frequency: ''
    

    And change the Label to:

    Label:
        id: _frequenz
        text:  root.frequency
        font_size: 20
    

    But to actually change the value shown in the label, you will need a reference to the instance of OutputParameters, using something like:

    App.get_running_app().root.ids._output_parameters.frequency = str(500)