![]() |
Update Gtk.Label in for-loop - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: Update Gtk.Label in for-loop (/thread-10809.html) |
Update Gtk.Label in for-loop - TimeMen - Jun-07-2018 How can I update a Gtk.Label in a foor loop? It's not updating via .set_text("bbb"). Is there any trick to do this? Greetings TimeMen RE: Update Gtk.Label in for-loop - buran - Jun-07-2018 post your code in python tags and full traceback if you get any exception RE: Update Gtk.Label in for-loop - TimeMen - Jun-07-2018 for zahl in range(start, end+1): function(self, zahl, steps, counter, prim_counter) counter +=1 if not numlist: if not divlist: if zahl > 1: prim_counter += 1 elif divlist: kpt_counter += 1 elif numlist == divlist: if (sqrt(zahl).is_integer()): psq_counter += 1 else: pt_counter +=1 if numlist != divlist: gt_counter += 1 val = self.progressbar.get_fraction() + 1/end self.progressbar.set_fraction(val)This is the code, after changing the Label to a Progressbar (as you can see.) But it won't work too. There's no exception, It's just not working. Only at the end, the progressbar is completely filled. It's only kinda bar, not a "progress"bar.. RE: Update Gtk.Label in for-loop - killerrex - Jun-07-2018 The problem is that while your application is in the loop it does not allow Gtk to control the GUI (it just "freezes") so only the final modification is effective. So if your application is going to perform a heavy operation the best option is to launch it in a different process and set a communication channel to be able to check the progress. To do this you can use the multiprocessing module (it is easier than it looks) Now you can set a timer in the GUI that periodically check the state of your task and update the progressbar. As the explanation is a little bit confusing, there is a demo code: #!/usr/bin/env python3 import multiprocessing as mp import time import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject def really_looong_operation(state): """ Do something that will block your app for a long time """ # tick every 200 milliseconds tick = 0.2 state.value = 0 for k in range(100): # In real life this might be invert a huge matrix or whatever... time.sleep(tick) state.value = k + 1 # Final activity... time.sleep(2*tick) class PBarDemo(Gtk.Window): def __init__(self): super().__init__(title="Progressing...") self.connect("destroy", Gtk.main_quit) self.set_border_width(10) vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5) self.add(vbox) self.pbar = Gtk.ProgressBar() self.pbar.set_show_text(True) vbox.pack_start(self.pbar, True, True, 0) self.switch = Gtk.Switch() self.switch.connect("notify::active", self.on_start_stop) vbox.pack_start(self.switch, True, True, 0) self.tid = None self.proc = None self.state = mp.Value('i', 0) # Guarantee the start state self._stop() def _stop(self): # Guarantee that everything is in "stop mode" if self.tid is not None: GObject.source_remove(self.tid) if self.proc is not None and self.proc.is_alive(): self.proc.terminate() self.tid = None self.proc = None self.pbar.set_fraction(0.0) self.pbar.set_text('Ready...') def on_start_stop(self, switch, prop): # Check this is the right property if prop.name != "active": return self._stop() if not switch.get_active(): return # Launch the activity... depending of what you want to do, # it might be better to use a pool of workers or other tricks self.proc = mp.Process(target=really_looong_operation, args=(self.state,)) self.proc.start() # And the timer that update the progressbar self.tid = GObject.timeout_add(250, self.running, None) self.pbar.set_text("0%") def running(self, ignored): value = self.state.value if value >= 100: # Stop working at 100% self.proc.join() self._stop() self.switch.set_active(False) # Return false to stop the timer return False else: frac = value / 100 self.pbar.set_fraction(frac) self.pbar.set_text(f"{frac:.0%}") # Return True so this timer is considered active return True if __name__ == '__main__': win = PBarDemo() win.show_all() Gtk.main() |