I'm developing a graphical interface with pygtk 3, In parallel with this interface, I'm running a function in a 2nd thread, which reads a file that is updated by an external program.
When the value in this file exceeds a certain value, I'd like to display a popup window to warn the user that this value has been reached.
The problem is that when the popup window is displayed, the program freeze.
After looking at several similar questions, I've understood that you can't launch another gtk window in a second thread, but no matter how hard I look, I can't figure out how to do it...maybe by emitting a signal from the thread that would be picked up by gtk main loop? but I haven't figured out how to do it properly.
here is a simplified code(i didn't put all the code of the GUI it's to big and no relevent for this issue), so just a main gtk window, a popup window and the function reading the file.
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
from threading import Thread
import time
#The Popup window classe
class DeepMonitorWindow(Gtk.Window):
def __init__(self):
super().__init__(title="Sounder")
self.set_border_width(10)
label=Gtk.Label(label="som popup message")
hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
hbox.pack_start(label,True,True,6)
button=Gtk.Button.new_with_label("OK")
button.connect("clicked",self.on_click)
hbox.pack_start(button,True,True,6)
self.add(hbox)
def on_click(self,event):
self.destroy()
#the function that run ine the thread
def DeepMonitor():
flagUpDown=True
while(1):
with open("seasave_shared.txt","r") as f:
depth=f.readlines()[-1]
print(float(depth.lstrip().strip("\n")))
if float(depth.lstrip().strip("\n")) > 150 and flagUpDown==True :
print("deep reached 150m")
window=DeepMonitorWindow()
window.show_all()
flagUpDown=False
if float(depth.lstrip().strip("\n")) < 150 and flagUpDown==False:
print("deep reached 150m")
window=DeepMonitorWindow()
window.show_all()
flagUpDown=True
break
time.sleep(1)
#the main window
class StationSheet():
def __init__(self):
self.window=Gtk.Window()
self.window.show_all()
self.window.connect("destroy", Gtk.main_quit)
#the thread
t=Thread(target=DeepMonitor)
t.start()
def main():
app = StationSheet()
Gtk.main()
if __name__ == "__main__":
main()
I finally found a way to make it work! I got my inspiration from the following link: https://pygobject.readthedocs.io/en/latest/guide/threading.html
use
lang-python GLib.idle_add(function)to display the window and uselang-python thread.deamon()before launching the thread.I've also created a function to display the popup window.
here's the working code