使用 GtkBuilder 自动连接信号时对话框会中断,但在手动连接信号时可以正常工作

发布于 2024-12-29 20:24:09 字数 3187 浏览 1 评论 0原文

我想要一个对话框窗口,其中某些按钮可以关闭对话框,而其他按钮则不能。我这样做的方法是使用来自 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()

当您运行它时,您会得到一个带有单个按钮的窗口。单击该按钮时,会弹出一个对话框,其中有两个按钮,一个标记为“不关闭对话框”,另一个标记为“关闭对话框”。运行上面的代码时,两个按钮都会关闭对话框。

来手动连接信号

        self.builder.connect_signals(self)

但是,如果您从使用 Gtk.Builder.connect_signals() 更改为通过替换

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

,那么它就会开始按设计工作(“不关闭对话框”按钮不会关闭对话框)。

但是在这种情况下,这两行代码在功能上不应该完全相同吗?有什么方法可以找出这两种情况之间的区别吗?

我可以看出在这两种情况下信号仍然连接,因为文本仍然从 DummyDialog.on_response 打印到 CLI。但当我使用 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))。

I want to have a dialog window where some buttons close the dialog and others don't. The way I do this is by using the response signal from the Gtk.Dialog to call emit_stop_by_name('response') on the dialog. (If someone knows of a better way of doing this, that might preempt the whole rest of this question.)

This worked when I used PyGTK. I'm moving to PyGObject now.. and it seems that this technique will work only if I manually connect to the response signal rather than using Gtk.Builder.connect_signals().

But don't take my word for it. Here is a minimal example of my problem:

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()

When you run this, you get a window with a single button. When you click that button, a dialog pops up with two buttons, one labeled "Don't Close Dialog" and another labeled "Close Dialog". When running the code above, both buttons will close the dialog.

But if you change from using Gtk.Builder.connect_signals() to manually connecting the signal by replacing

        self.builder.connect_signals(self)

with

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

then it starts working as designed (the "Don't Close Dialog" button doesn't close the dialog).

But shouldn't those two lines be exactly functionally identical in this context? Is there any way to figure out what's different between the two scenarios?

I can tell the signals are still connected in both situations because the text is still printed to the CLI from DummyDialog.on_response. But it seems like the widget.emit_stop_by_name('response') part stops working when I use GtkBuilder.

Even more perplexing is that if you take this exact code and run it on PyGTK (change from gi.repository import Gtk to import gtk as Gtk), then it works correctly in both scenarios (using self.builder.connect_signals(self) or self.dialog1.connect('response', self.on_response)).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

护你周全 2025-01-05 20:24:09

我会做得有点不同。删除按钮单击回调中的 dialog1.destroy() 并将 on_response 回调更改为:

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

I would do it a little different. Remove the dialog1.destroy() in the button clicked callback and change the on_response callback to:

    def on_response(self, widget, response, data=None):
        print 'response:', response
        if response < 0:
            self.dialog1.destroy()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文