如何用PyGTK/Gtkbuilder重复显示一个Dialog?

Jul*_*ian 9 python gtk pygtk dialog gtkbuilder

我创建了一个PyGTK应用程序,当用户按下按钮时会显示一个Dialog.该对话框在我的__init__方法中加载:

builder = gtk.Builder()
builder.add_from_file("filename")
builder.connect_signals(self) 
self.myDialog = builder.get_object("dialog_name")
Run Code Online (Sandbox Code Playgroud)

在事件处理程序中,对话框随命令一起显示self.myDialog.run(),但这只能运行一次,因为在run()对话框被自动销毁之后.如果我再次单击该按钮,应用程序将崩溃.

我读到有一种方法可以使用show()而不是run()对话框没有被销毁的地方,但我觉得这对我来说不是正确的方法因为我希望对话框能够以模态方式运行并且仅在用户之后将控制权返回给代码关闭了它.

有没有一种简单的run()方法可以使用gtkbuilder 使用该方法重复显示对话框?我尝试使用gtkbuilder重新加载整个对话框,但这似乎没有用,对话框缺少所有子元素(我更喜欢在程序开始时只使用构建器一次).


[解决方案](编辑)
正如下面的答案所指出的那样,使用hide()诀窍.我首先想到你仍然需要捕捉"删除事件",但这实际上没有必要.一个有效的简单示例是:


import pygtk
import gtk

class DialogTest:

    def rundialog(self, widget, data=None):
        self.dia.show_all()
        result = self.dia.run() 
        self.dia.hide()


    def destroy(self, widget, data=None):
        gtk.main_quit()

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("destroy", self.destroy)

        self.dia = gtk.Dialog('TEST DIALOG', self.window, 
           gtk.DIALOG_MODAL  | gtk.DIALOG_DESTROY_WITH_PARENT)
        self.dia.vbox.pack_start(gtk.Label('This is just a Test'))


        self.button = gtk.Button("Run Dialog")    
        self.button.connect("clicked", self.rundialog, None)
        self.window.add(self.button)
        self.button.show()
        self.window.show()



if __name__ == "__main__":
    testApp = DialogTest()
    gtk.main()
Run Code Online (Sandbox Code Playgroud)

pto*_*ato 5

其实,阅读文档Dialog.run().该对话框不会自动销毁.如果您hide()run()方法退出时使用它,那么您应该可以run()根据需要多次使用它.

或者,您可以将对话框设置为构建器文件中的模态,然后将show()其设置为模态.这将实现类似但不完全相同的效果run()- 因为run()创建了主GTK循环的第二个实例.

编辑

如果未连接delete-event信号,则会出现分段错误的原因是您单击关闭按钮两次.这是发生的事情:

  1. 单击"运行对话框",这将调用对话框的run()方法.
  2. 出现模态对话框,并启动其自己的主循环.
  3. 单击关闭按钮.对话框的主循环退出,但由于run()覆盖了关闭按钮的正常行为,因此不会关闭对话框.它也没有隐藏,所以它挂在身边.
  4. 您想知道为什么对话框仍然存在并再次单击关闭按钮.由于run()不再处于活动状态,因此触发关闭按钮的正常行为:对话框被销毁.
  5. 再次单击"运行对话框",尝试调用run()已销毁对话框的方法.崩溃!

因此,如果您确保hide()在步骤3之后的对话框,那么一切都应该工作.无需连接delete-event信号.