在线程中显示对话框

3 投票
2 回答
1520 浏览
提问于 2025-04-17 03:09

我有一个用pygtk写的程序,其中有一个gtk.Button()按钮。当我按下这个按钮时,它需要执行一个大约5秒钟的任务。所以我想在信号处理函数里用线程来实现这个耗时的功能。

首先,我在开头加了gtk.gdk.threads_init()这行代码。

我的信号处理函数叫def send_sms(),在这个函数里,我又定义了一个叫def send_sms_mycantos()的函数,并把它作为线程来调用。

threading.Thread(target = self.send_sms_mycantos, args=(phone_no, message_text, username, password)).start()

我还有一个函数用来显示对话框。

def dialog_notification(self, message, dialog_type):
    dlg = gtk.MessageDialog(self.window, gtk.DIALOG_DESTROY_WITH_PARENT, dialog_type, gtk.BUTTONS_CLOSE, message)
    dlg.run()
    dlg.destroy()

现在,如果我在我的线程里调用上面的那个函数

self.dialog_notification("Message sent successfully", gtk.MESSAGE_INFO)

我就会遇到一个错误。

SMSSender.py: Fatal IO error 11 (Resource temporarily unavailable) on X server :0.0.

这样实现线程的方式对吗?我哪里做错了?这个错误的意思是线程似乎不知道Xserver正在运行。

2 个回答

0

这个错误出现是因为你在一个线程中更新了图形用户界面(GUI)。

每次你想访问图形用户界面时,都应该使用 Gdk.threads_enter()Gdk.threads_leave()(你需要先导入 Gdk)。

def dialog_notification(self, message, dialog_type):
    dlg = gtk.MessageDialog(self.window, gtk.DIALOG_DESTROY_WITH_PARENT, dialog_type, gtk.BUTTONS_CLOSE, message)
    Gdk.threads_enter()
    dlg.run()
    Gdk.threads_leave()

    Gdk.threads_enter()
    dlg.destroy()
    Gdk.threads_leave()
2

最简单的方法就是在主 gtk 线程中运行 self.dialog_notification()。只需在你的线程中添加 gobject.idle_add(self.dialog_notification, args...) 这行代码就可以了。

撰写回答