显示来自线程的弹出窗口 pygtk 使 GUI 冻结

show popup window from a thread pygtk make GUI freeze

提问人:Igloot 提问时间:10/13/2023 最后编辑:Igloot 更新时间:10/16/2023 访问量:25

问:

我正在使用 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()
python-3.x python-多线程 pygtk

评论


答:

0赞 Igloot 10/16/2023 #1

我终于找到了让它工作的方法!我从以下链接中获得了灵感: https://pygobject.readthedocs.io/en/latest/guide/threading.html

用于显示窗口,并在启动线程之前使用。 lang-python GLib.idle_add(function) lang-python 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()