我正在使用 pygtk 3 开发图形界面, 与此接口并行,我在第二个线程中运行一个函数,该函数读取由外部程序更新的文件。
当此文件中的值超过某个值时,我想显示一个弹出窗口来警告用户已达到该值。
问题是当弹出窗口显示时,程序冻结。
在查看了几个类似的问题后,我明白你不能在第二个线程中启动另一个 gtk 窗口,但无论我多么努力地寻找,我都不知道如何做到这一点......也许通过发出来自线程的信号将被 gtk 主循环拾取?但我还没弄清楚如何正确地做到这一点。
这里是一个简化的代码(我没有把GUI的所有代码都放出来,它太大了,与这个问题无关),所以只有一个主gtk窗口,一个弹出窗口和读取文件的函数。
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()
我终于找到了让它发挥作用的方法!我从以下链接中获得了灵感:https://pygobject.readthedocs.io/en/latest/guide/threading.html
使用 GLib.idle_add(function) 显示窗口并在启动线程之前使用 thread.deamon() 。
我还创建了一个显示弹出窗口的函数。
这是工作代码
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 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=self.DeepMonitor)
t.daemon=True
t.start()
#the function that run ine the thread
def show_popup(self):
p=DeepMonitorWindow()
p.set_transient_for(self.window)
p.show_all()
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)
def main():
app = StationSheet()
Gtk.main()