gtk MessageDialog 直到外部方法结束才关闭
这是我在图形界面中想要实现的一个效果的模拟版本。我有一个消息对话框(MessageDialog),它是在某个回调方法执行时创建的。我的问题是,这个消息对话框在回调方法执行完之前是无法关闭的。
我有一个“dialog.destroy()”的代码,我本以为这段代码可以关闭对话框。我点击“是/否”按钮,按钮确实被按下了,但对话框在“_go”方法执行完之前不会消失。
这里的“time.sleep(4)”是为了模拟在我与消息对话框互动结束后,“_go”方法中还会有其他事情发生。
from gi.repository import Gtk, GObject
import time
class Gui(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect("delete_event", Gtk.main_quit)
self.set_size_request(700, 600)
notebook = Gtk.Notebook()
notebook.set_tab_pos(Gtk.PositionType.TOP)
notebook.append_page(MyTab(), Gtk.Label("A tab"))
self.add(notebook)
notebook.show_all()
self.show()
class MyTab(Gtk.VBox):
def __init__(self):
super(MyTab, self).__init__()
self.go_button = Gtk.Button()
self.go_button.add(Gtk.Image().new_from_stock(Gtk.STOCK_APPLY,
Gtk.IconSize.BUTTON))
top_box = Gtk.HBox()
top_box.pack_start(self.go_button, False, True, 5)
self.pack_start(top_box, False, True, 5)
# setup callbacks
self.go_button.connect("clicked", self._go)
def _go(self, _):
dialog = Gtk.MessageDialog(Gtk.Window(),
Gtk.DialogFlags.MODAL,
Gtk.MessageType.QUESTION,
Gtk.ButtonsType.YES_NO,
"RESPONSE REQUIRED")
dialog.format_secondary_text("are you having fun?")
response = dialog.run()
dialog.destroy()
print "your response is: " + str(response)
time.sleep(4)
print "left _go"
def main():
"""
Main entry point.
"""
Gui()
Gtk.main()
if __name__ == "__main__":
main()
3 个回答
1
这是正常的情况。窗口只有在控制权返回给Gtk的主循环时才会消失,而这只会在你的_go回调函数结束时发生。
3
这个问题并不是只发生在对话框上。任何图形界面的变化在你回到主循环之前都是看不见的,系统需要时间来处理那些因为修改了控件而积累的事件。
如果你真的想在回调函数中立即更新图形界面,可以在调用dialog.destroy()
之后,手动用一个循环来处理这些积累的事件,像这样:
while Gtk.events_pending():
Gtk.main_iteration()
不过要注意,这样做不仅会更新屏幕,还会运行其他积累的事件,包括空闲时间和超时处理程序,以及按钮点击的回调(如果有的话)。这可能会导致一些意想不到的结果。
1
根据user4815162342的回答中的评论,我想出了一个解决方案,使用了嵌套的主循环。这个类接收一个对话框,并提供一个运行方法。
class NestedDialog(object):
def __init__(self, dialog):
self.dialog = dialog
self.response_var = None
def run(self):
self._run()
return self.response_var
def _run(self):
self.dialog.show()
self.dialog.connect("response", self._response)
Gtk.main()
def _response(self, dialog, response):
self.response_var = response
self.dialog.destroy()
Gtk.main_quit()
然后对话框的运行方式如下:
def _go(self, _):
dialog = Gtk.MessageDialog(Gtk.Window(),
Gtk.DialogFlags.MODAL,
Gtk.MessageType.QUESTION,
Gtk.ButtonsType.YES_NO,
"RESPONSE REQUIRED")
dialog.format_secondary_text("are you having fun?")
nested_dialog = NestedDialog(dialog)
response = nested_dialog.run()
print "your response is: " + str(response)
time.sleep(4)
print "left _go"