rawpython / remi

Python REMote Interface library. Platform independent. In about 100 Kbytes, perfect for your diet.
Apache License 2.0
3.48k stars 401 forks source link

How to make a widget moving(change its position) iteratively? #440

Closed hcygeorge closed 3 years ago

hcygeorge commented 3 years ago

I want to make a widget change its position many times by looping after clicked.
I have tried using a for loop, but when I click the widget, it just move to the final position after the whole loop is done. Any idea to make this possible?

dddomodossola commented 3 years ago

Hello @hcygeorge , you should do it in a thread. Such thread can be initiated by the button click. When you make changes to a widget by a separate thread you must use the update_lock to prevent concurrent access. Here is an example, here a label and a progress_bar are update by a thread

import remi.gui as gui
from remi import start, App
import threading
import time

class MyApp(App):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

    def main(self):
        # margin 0px auto allows to center the app to the screen
        wid = gui.VBox(width=300, height=200, margin='0px auto')
        self.lbl = gui.Label('Thread status', width='80%', height='50%')
        self.lbl.style['margin'] = 'auto'

        self.progress_bar = gui.Progress()

        wid.append(self.lbl)
        wid.append(self.progress_bar)

        # Here I start a parallel thread that executes my algorithm for a long time
        t = threading.Thread(target=self.my_intensive_long_time_algorithm)
        t.start()

        # returning the root widget
        return wid

    def my_intensive_long_time_algorithm(self):
        time.sleep(3.0)

        #use the update lock when you want to change a widget
        with self.update_lock:
            self.lbl.set_text('Algorithm started')
            self.progress_bar.set_value(1)

        #DO other activities outside the update lock, otherwise the widgets are not updated
        #here you can do your calculations, I use a sleep to simulate calculations time
        time.sleep(1.0)

        #use the update lock when you want to change a widget
        with self.update_lock:
            self.lbl.set_text('Algorithm 20%')
            self.progress_bar.set_value(20)

        #DO other activities outside the update lock, otherwise the widgets are not updated
        #here you can do your calculations, I use a sleep to simulate calculations time
        time.sleep(1.0)

        #use the update lock when you want to change a widget
        with self.update_lock:
            self.lbl.set_text('Algorithm 40%')
            self.progress_bar.set_value(40)

        #DO other activities outside the update lock, otherwise the widgets are not updated
        #here you can do your calculations, I use a sleep to simulate calculations time
        time.sleep(1.0)

        progress = 40
        for i in range(0, 10):
            #use the update lock when you want to change a widget
            with self.update_lock:
                self.lbl.set_text('Now executing a for statement')
                progress += 11
                self.progress_bar.set_value(progress)

            #DO other activities outside the update lock, otherwise the widgets are not updated
            #here you can do your calculations, I use a sleep to simulate calculations time
            time.sleep(0.5)

        #DO other activities outside the update lock, otherwise the widgets are not updated
        #here you can do your calculations, I use a sleep to simulate calculations time
        time.sleep(1.0)

        #use the update lock when you want to change a widget
        with self.update_lock:
            self.lbl.set_text('Algorithm terminated')
            self.progress_bar.set_value(100)

if __name__ == "__main__":
    start(MyApp, debug=True, address='0.0.0.0', port=0, update_interval=0.1)