pd shah
pd shah

Reputation: 1406

un_active button until function finished in kivy

I am using kivy for UI. there is a Time_consuming function and when it runs, kivy ui will goes in black, so I used Threading. I want to disable buttons until Time_consuming function finishes, and then enable button again. I have been used something like below:

from threading import Thread
from kivy.clock import Clock
from functools import partial

   def run():
        self.run_button.disabled=True
        self.back_button.disabled=True

        t=Thread(target=Time_consuming(), args=())
        t.start()

        Clock.schedule_interval(partial(disable, t.isAlive()), 8)

    def disable(t, what):
        print(t)
        if not t:
            self.run_button.disabled=False
            self.back_button.disabled=False

but this dose not work, t.isAlive() in disable() even when Time_consuming() finishes, is True. where is the problem ?

question2: another problem is, Clock.schedule_interval will continue to run for ever. how can stop it when function finished?

Upvotes: 0

Views: 1458

Answers (2)

PalimPalim
PalimPalim

Reputation: 3048

I see you already answered your question. I was also building an example app to help you, while you were answering. I think it still can be of value to you and therefore I am posting it. One button shows you threading and the other one scheduling once. Happy coding :).

from kivy.app import App
from kivy.base import Builder
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock

import time
import threading


Builder.load_string("""
<rootwi>:
    label_to_be_changed1: label_to_be_changed1
    label_to_be_changed2: label_to_be_changed2
    button1: button1
    button2: button2
    orientation: 'vertical'
    Button:
        id: button1
        text:'Button1 - Threading'
        on_press: root.change_Label_text1()
    Button:
        id: button2
        text: 'Button2 - schedule'
        on_press: root.change_Label_text2()
    Label:
        id: label_to_be_changed1
    Label:
        id: label_to_be_changed2
""")
class rootwi(BoxLayout):
    label_to_be_changed1 = ObjectProperty()
    label_to_be_changed2 = ObjectProperty()
    button1 = ObjectProperty()
    button2 = ObjectProperty()


    def change_Label_text1(self):
        self.button1.disabled = True
        threading.Thread(target=self.timeconsuming).start()

    def timeconsuming(self):
        #do your stuff
        time.sleep(5)
        self.label_to_be_changed1.text = 'thread has ended'
        self.button1.disabled = False

    def change_Label_text2(self):
        self.button2.disabled = True
        Clock.schedule_once(self.change_Label_text2_callback, 4)

    def change_Label_text2_callback(self, *largs):
        self.label_to_be_changed2.text = 'schedule has ended'
        self.button2.disabled = False

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

if __name__ == '__main__':
    MyApp().run()

Upvotes: 1

pd shah
pd shah

Reputation: 1406

I have found that:

question1: pass t instead of t.isAlive().this :

Clock.schedule_interval(partial(disable, t.isAlive()), 8)

changed to :

Clock.schedule_interval(partial(disable, t), 8)

question2: If the disable() returns False, the schedule will be canceled and won’t repeat.

def run_model():
    self.run_button.disabled=True
    self.back_button.disabled=True

    t=Thread(target=run, args=())
    t.start()

    Clock.schedule_interval(partial(disable, t), 8)

def disable(t, what):
    if not t.isAlive():
        self.run_button.disabled=False
        self.back_button.disabled=False
        return False

Upvotes: 0

Related Questions