Eka
Eka

Reputation: 15000

How to get Id and Text value of a kivy button as string?

I have an app with multiple buttons and I need to get id and text value of the button as string when it is pressed. The grabbed Ids and Text valus of the button will then be passed to another function for further processing. For simplicity I wrote this sample programme.

# main.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

########################################################################
class KVMyHBoxLayout(BoxLayout):
    pass


########################################################################
class ExampleApp(App):
    def Pressbtn(self, *args):
        print'Pressed button'
    #----------------------------------------------------------------------
    def build(self):

        return KVMyHBoxLayout()

#----------------------------------------------------------------------
if __name__ == "__main__":
    app = ExampleApp()
    app.run()

kv file

<MyButton@Button>:
    color: .8,.9,0,1
    font_size: 32

<KVMyHBoxLayout>:
    orientation: 'vertical'
    MyButton:
        id:"idBtn1"
        text: "Btn1"
        background_color: 1,0,0,1
        on_press:app.Pressbtn()
    MyButton:
        id:"idBtn2"
        text: "Btn2"
        background_color: 0,1,0,1
        on_press:app.Pressbtn()
    Label:
        text: "ID"
        background_color: 0,0,1,1
    Label:
        text: "Text"
        background_color: 1,0,1,1

When a button is pressed its corresponding values of id and text will be shown in the ID and Text labels. Currently the above code only print Pressed button when button is pressed. I want to know how to get id and text value of button pythonically.

Upvotes: 2

Views: 16169

Answers (3)

Kanad Patil
Kanad Patil

Reputation: 256

example to get button text on button click :

class MainApp(MDApp):
def build(self):

    VB = BoxLayout(orientation='vertical', padding=50,spacing="10")

    Atbtn = Button(text="AT (Automata Theory)", font_size="25sp")
    Atbtn.bind(on_press=self.callback)

    Pybtn = Button(text="Python", font_size="25sp")
    Pybtn.bind(on_press=self.callback)


    VB.add_widget(Atbtn)
    VB.add_widget(Pybtn)

    return VB

def callback(self, instance):
    print(instance.text)

Upvotes: 0

DrewTNBD
DrewTNBD

Reputation: 41

You can use a callback function something along these lines. In your KV file:

 ToggleButton:
     text: 'Label'
     id: halftimebutton
     on_state: root.callback(self)

And then in your .py file you can do this:

def callback_halftime_state(self, instance):
    if instance.state == 'down':
        self.halftime == True
    else:
        self.halftime == False

This is of course showing the instance.state - but it could be any attribute of the button that Kivy exposes; instance.text, instance.id, etc.

Upvotes: 0

FJSevilla
FJSevilla

Reputation: 4513

First, you must pass the button instance explicitly to the method when it is called from the kv:

on_press: app.Pressbtn(self)

You can then use the instance reference to modify the button or see its attributes, you do not need the id. If you want to get the id, you can only do it using the ids dictionary of the button parent.

An example based on your code:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

kv_file = '''
<MyButton@Button>:
    color: .8,.9,0,1
    font_size: 32

<KVMyHBoxLayout>:
    orientation: 'vertical'
    MyButton:
        id:"idBtn1"
        text: "Btn1"
        background_color: 1,0,0,1
        on_press:app.Pressbtn(self)
    MyButton:
        id:"idBtn2"
        text: "Btn2"
        background_color: 0,1,0,1
        on_press:app.Pressbtn(self)
    Label:
        id: lobj
        text: "Object"
        background_color: 1,0,1,1

    Label:
        id: lid
        text: "ID"
        background_color: 0,0,1,1
    Label:
        id: ltext
        text: "Text"
        background_color: 1,0,1,1
'''


class KVMyHBoxLayout(BoxLayout):
    pass

class ExampleApp(App):
    def Pressbtn(self, instance):
        instance.parent.ids.lobj.text = str(instance)
        instance.parent.ids.ltext.text = instance.text
        instance.parent.ids.lid.text= self.get_id(instance)

    def get_id(self,  instance):
        for id, widget in instance.parent.ids.items():
            if widget.__self__ == instance:
                return id

    def build(self):
        Builder.load_string(kv_file)
        return KVMyHBoxLayout()

if __name__ == "__main__":
    app = ExampleApp()
    app.run()

Output:

enter image description here

Edit:

If you define the widget (button) in the .py file you do not need to pass the instance to the function, it is passed automatically as argument:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView


class FirstScreen(Screen):
    def __init__(self,**kwargs):
        super(FirstScreen, self).__init__(**kwargs)    
        layout=BoxLayout(orientation="vertical",size_hint_y= None)
        layout.bind(minimum_height=layout.setter('height'))                
        for i in range(50):
                btn = Button(text="Button"+str(i),
                             id=str(i),
                             size_hint=(None, None),
                             on_press=self.Press_auth)               #<<<<<<<<<<<<<<<<           
                layout.add_widget(btn)
        root = ScrollView()
        root.add_widget(layout)
        self.add_widget(root)

    def Press_auth(self,instance):     
        print(str(instance))

class TestScreenManager(ScreenManager):
    def __init__(self,  **kwargs):
        super(TestScreenManager,  self).__init__(**kwargs)
        self.add_widget(FirstScreen())

class ExampleApp(App):
    def build(self):           
        return TestScreenManager()

def main():
    app = ExampleApp()
    app.run()

if __name__ == '__main__':
    main()

Upvotes: 7

Related Questions