Python Kivy: correctly run a background process that updates GUI elements

I have a Python script that does some intensive processing of user files and may take some time. I create a user interface for him using Kivy, which allows the user to select a file, processing mode and display some messages in the process.

My problem is that when the Kivy main loop passes the calls to the base user interface, the window freezes.

From what I understood, the correct way to solve this is to create a separate process that will disable the script and from which it will send updates to the user interface.

However, I could not find an example of how to do this or any specification on how to send messages from a separate thread back to the application.

Can someone please give an example of how to do this correctly, or point me to the documentation related to the topic?

Update:

To support a supported program, I would like to avoid invoking processor cycle elements from the main thread and instead invoke one long process that returns to the updated GUI elements, such as a progress bar or text field. It seems that these elements can only be changed from the main kiwi. How to access them from the outside?

+4
source share
2 answers

/, . , :

from kivy.app import App
from kivy.clock import Clock, _default_time as time  # ok, no better way to use the same clock as kivy, hmm
from kivy.lang import Builder
from kivy.factory import Factory
from kivy.uix.button import Button
from kivy.properties import ListProperty

from threading import Thread
from time import sleep

MAX_TIME = 1/60.

kv = '''
BoxLayout:
    ScrollView:
        GridLayout:
            cols: 1
            id: target
            size_hint: 1, None
            height: self.minimum_height

    MyButton:
        text: 'run'

<MyLabel@Label>:
    size_hint_y: None
    height: self.texture_size[1]
'''

class MyButton(Button):
    def on_press(self, *args):
        Thread(target=self.worker).start()

    def worker(self):
        sleep(5) # blocking operation
        App.get_running_app().consommables.append("done")

class PubConApp(App):
    consommables = ListProperty([])

    def build(self):
        Clock.schedule_interval(self.consume, 0)
        return Builder.load_string(kv)

    def consume(self, *args):
        while self.consommables and time() < (Clock.get_time() + MAX_TIME):
            item = self.consommables.pop(0)  # i want the first one
            label = Factory.MyLabel(text=item)
            self.root.ids.target.add_widget(label)

if __name__ == '__main__':
    PubConApp().run()
+4

: kivy , , . ( .) kivy , .

+1

All Articles