gtk MessageDialog在封闭方法完成之前不会关闭

时间:2013-02-14 23:36:11

标签: python dialog gtk pygtk messagedialog

这是我在GUI中尝试做的模拟版本。我有一个MessageDialog,它是在执行回调方法的过程中创建的。我的问题是MessageDialog在回调方法完成执行之前不会关闭。

我有一个“dialog.destroy()”我希望破坏对话框。我单击“是/否”并按下按钮,但在“_go”结束之前对话框不会消失。

在我的MessageDialog交互结束后,“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 个答案:

答案 0 :(得分:3)

此问题并非特定于对话框。 任何 GUI更改都是不可见的,直到您返回主循环并让系统有机会处理通过修改小部件而累积的事件。

如果你真的想立即在回调中更新GUI,你可以在调用dialog.destroy()之后用这样的循环手动旋转累积的事件:

while Gtk.events_pending():
    Gtk.main_iteration()

但是,请注意,这不仅会更新屏幕,还会运行其他累积事件,包括空闲和超时处理程序以及按钮单击回调(如果有任何待处理的事件)。这可能会产生意想不到的后果。

答案 1 :(得分:1)

这是正确的行为。当控制权返回给Gtk的主循环时,窗口才会消失,这只发生在_go回调结束时。

答案 2 :(得分:1)

根据对user4815162342's answer的评论,我想出了一个使用嵌套主循环的解决方案。该类接受一个对话框并提供一个run方法。

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"