SmallPythonProjects/GTK-examples/liveProgressBar.py
2021-07-01 14:17:59 +02:00

103 lines
2.9 KiB
Python

import multiprocessing as mp
import time
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
def really_looong_operation(state):
"""
Do something that will block your app for a long time
"""
# tick every 200 milliseconds
tick = 1
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)
GLib.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.tid = GLib.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()
try:
Gtk.main()
except:
exit()