Kivy and Python threading - how get data between them

13,153

This will probably solve all your problems. That's the way I like to code while dealing with threads and with kivy language.

Here is thread.py file

import threading   
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty

class Thread(BoxLayout):
    counter = NumericProperty(0)

    def Counter_function(self):
        self.counter += 1
        self.ids.lbl.text = "{}".format(self.counter)

    def First_thread(self):
        threading.Thread(target = self.Counter_function).start()
        self.counter += 1
        self.ids.lbl.text = "{}".format(self.counter)

class MyApp(App):
    def build(self):
        self.load_kv('thread.kv')
        return Thread() 

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

Here is thread.kv file

<Thread>:
    Button:
        text: "use thread"
        on_release: root.First_thread()
    Button:
        text: "Hit me"
        on_release: root.Counter_function()
    Label:
        id: lbl
        text: "Numbers"

Now, You said in your comment that you struggle with dynamically loading the GUI. So, here's an example. threading.py

import threading   
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty
from kivy.lang.builder import Builder
from kivy.uix.button import Button

Builder.load_string('''
[SideBar@BoxLayout]:
    content: content
    orientation: 'vertical'
    size_hint: .2,1
    BoxLayout:
        orientation: 'vertical'
        # just add a id that can be accessed later on
        id: content

<Root>:
    Button:
        center_x: root.center_x
        text: 'press to add_widgets'
        size_hint: .2, .2
        on_press:
            sb.content.clear_widgets()
            root.load_content(sb.content)
    SideBar:
        id: sb
''')

class Root(BoxLayout):

    def load_content(self, content):
        for but in range(20):
            content.add_widget(Button(text=str(but)))

class MyApp(App):
    def build(self):
        return Root()

if __name__ == "__main__":
    app = MyApp()
    app.run()
Share:
13,153

Related videos on Youtube

user3082089
Author by

user3082089

Updated on September 29, 2022

Comments

  • user3082089
    user3082089 over 1 year

    I've some problems with python(threading) and kivy:

    Here is some code:

    import kivy
    import threading 
    import time
    from kivy.app import App
    from kivy.uix.button import Button
    
    class Thread(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)  
            self.counter = 0        
        def run(self):
            while True:
                print "Thread is running "+str(self.counter)
                app.button.text = self.set_button(self.counter)
                app.button.text = str(self.counter)
                time.sleep(0.5)
        def count(self):
            self.counter += 1
            app.button.text = str(self.counter)     
        def set_button(self, value):
            app.button.text = str(value)
    
    class MyApp(App):
        def __init__ (self, thread_object):
            App.__init__(self) 
            self.thread_object = thread_object      
        def callback(self,instance):
            print('The button <%s> is being pressed' % instance.text)
            self.thread_object.count()
        def build(self):
            self.button = Button(text='Hello World')
            self.button.bind(on_press=self.callback)
            return self.button
    
    thread = Thread()
    thread.start()
    app = MyApp(thread)
    app.run()
    

    Now - this code opens a kivy app with one button. The task is: pressing the button some data should appear in the threaded code (it does by the "count" method.

    Problem is the reverse way - the threaded code should change the text of the button. I've tried two ways:

    • Write it directly: app.button.text = str(self.counter)

    • Write it via a method "set_button": app.button.text = self.set_button(self.counter)

    Both of them show up an error "Attribute Error: 'MyApp' object has no attribute 'button'".

    Is there any way to exchange data directly without requesting, even without doing that pointer stuff here with "thread_object"

    def __init__ (self, thread_object):
    

    Thanks for your help.

  • Alex
    Alex almost 3 years
    The Counter_function doesn't seem to end when the main application quits.