使用GtkBuilder自动连接信号时对话框出错,但手动连接信号时正常

6 投票
1 回答
832 浏览
提问于 2025-04-17 11:55

我想要一个对话框窗口,其中一些按钮可以关闭对话框,而另一些则不能。我的做法是使用Gtk.Dialogresponse信号,通过调用emit_stop_by_name('response')来处理对话框的关闭。(如果有人知道更好的方法,可以直接解决这个问题,那就太好了。)

在我使用PyGTK的时候,这个方法是有效的。现在我转向使用PyGObject,似乎这个技巧只有在我手动连接响应信号时才有效,而不能使用Gtk.Builder.connect_signals()

但别光听我说,这里有一个简单的例子来说明我的问题:

from gi.repository import Gtk

xml = """<interface>
  <object class="GtkDialog" id="dialog1">
    <signal name="response" handler="on_response"/>
    <child internal-child="vbox">
      <object class="GtkBox" id="dialog-vbox1">
        <child internal-child="action_area">
          <object class="GtkButtonBox" id="dialog-action_area1">
            <child>
              <object class="GtkButton" id="button1">
                <property name="label">Don't Close Dialog</property>
                <property name="visible">True</property>
              </object>
            </child>
            <child>
              <object class="GtkButton" id="button2">
                <property name="label">Close Dialog</property>
                <property name="visible">True</property>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
    <action-widgets>
      <action-widget response="0">button1</action-widget>
      <action-widget response="-6">button2</action-widget>
    </action-widgets>
  </object>
</interface>
"""

def on_button_clicked(widget):
    d = DummyDialog()
    d.dialog1.run()
    d.dialog1.destroy()

class DummyDialog:
    def __init__(self):
        self.builder = Gtk.Builder()
        self.builder.add_from_string(xml)
        self.dialog1 = self.builder.get_object('dialog1')
        self.builder.connect_signals(self)

    def on_response(self, widget, response, data=None):
        print 'response:', response
        if response >= 0:
            widget.emit_stop_by_name('response')

w = Gtk.Window()
w.connect('destroy', Gtk.main_quit)
b = Gtk.Button('Open Dialog')
b.connect('clicked', on_button_clicked)
w.add(b)

w.show_all()

Gtk.main()

当你运行这个代码时,会出现一个只有一个按钮的窗口。当你点击这个按钮时,会弹出一个对话框,里面有两个按钮,一个标记为“不要关闭对话框”,另一个标记为“关闭对话框”。在运行上面的代码时,这两个按钮都会关闭对话框。

但是如果你把Gtk.Builder.connect_signals()换成手动连接信号,替换掉

        self.builder.connect_signals(self)

        self.dialog1.connect('response', self.on_response)

那么它就会按照预期工作(“不要关闭对话框”按钮不会关闭对话框)。

但在这个情况下,这两行代码不应该是完全相同的功能吗?有没有办法找出这两种情况之间的不同之处?

我可以确认在这两种情况下信号仍然是连接的,因为DummyDialog.on_response中的文本仍然会打印到命令行界面。但似乎当我使用GtkBuilder时,widget.emit_stop_by_name('response')这一部分就失效了。

更让人困惑的是,如果你把这段代码在PyGTK上运行(把from gi.repository import Gtk改为import gtk as Gtk),那么在这两种情况下它都能正常工作(使用self.builder.connect_signals(self)self.dialog1.connect('response', self.on_response))。

1 个回答

2

我会稍微换个方式来做。把按钮点击后的回调函数中的 dialog1.destroy() 去掉,然后把 on_response 的回调函数改成:

    def on_response(self, widget, response, data=None):
        print 'response:', response
        if response < 0:
            self.dialog1.destroy()

撰写回答