为什么在 Glade 和代码中添加时使用不同的参数调用事件处理程序?

Why is the event handler called with different parameters when added in Glade vs. in code?

以下是 4 个文件:

案例 #1example1.py 使用 example1.glade .

案例 #2example2.py 使用 example2.glade .

要查看两种情况下的输出,每种情况的步骤都是相同的。打开这些程序之一后,只需单击多行标签或 link 按钮,输出将显示在终端中。

截图,两种情况相同

第一个案例

example1.py

# coding=utf-8

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


def box_clicked(*args):
    print(args)
    return True


b = Gtk.Builder()
b.add_from_file("example1.glade")
w = b.get_object("window1")
lb = b.get_object("linkButton")
eb = b.get_object("eventbox1")
eb.connect("button-release-event", box_clicked, lb)

w.connect("delete-event", Gtk.main_quit)
w.show_all()
Gtk.main()

example1.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkAspectFrame">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="label_xalign">0</property>
        <child>
          <object class="GtkEventBox" id="eventbox1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="above_child">True</property>
            <child>
              <object class="GtkBox" id="box1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="orientation">vertical</property>
                <child>
                  <object class="GtkLinkButton" id="linkButton">
                    <property name="label" translatable="yes">button</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="relief">none</property>
                    <property name="uri">http://www.google.com</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="multilineLabel">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">this
is
a
multiline
label</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

信号和处理程序是通过代码手动连接的。

传递给信号处理程序的参数示例,打印为 print(args):

(<Gtk.EventBox object at 0x02bc4b6c (GtkEventBox at 0x02b9e290)>, <Gdk.EventButt
on object at 0x02bc4c34 (void at 0x02e691c8)>, <Gtk.LinkButton object at 0x02668
914 (GtkLinkButton at 0x02e37120)>)

印刷精美:

  1. Gtk.EventBox
  2. Gtk.EventButton
  3. Gtk.LinkButton

第二种情况

example2.py

# coding=utf-8

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class Builder(Gtk.Builder):
    def __init__(self):
        Gtk.Builder.__init__(self)
        self.add_from_file("example2.glade")
        self.connect_signals(self)
        self.win = self.get_object("window1")

    def box_clicked(self, *args):
        print(args)
        return True


win = Builder().win
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

example2.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window1">
    <property name="can_focus">False</property>
    <child>
      <object class="GtkAspectFrame">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="label_xalign">0</property>
        <child>
          <object class="GtkEventBox" id="eventbox1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="above_child">True</property>
            <signal name="button-release-event" handler="box_clicked" object="linkButton" swapped="no"/>
            <child>
              <object class="GtkBox" id="box1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="orientation">vertical</property>
                <child>
                  <object class="GtkLinkButton" id="linkButton">
                    <property name="label" translatable="yes">button</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="relief">none</property>
                    <property name="uri">http://www.google.com</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkLabel" id="multilineLabel">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="label" translatable="yes">this
is
a
multiline
label</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

事件处理程序已连接到 Glade 中的信号。

传递给信号处理程序的参数示例,打印为 print(args):

(<Gtk.LinkButton object at 0x02c68554 (GtkLinkButton at 0x02e96118)>, <Gdk.Event
Button object at 0x02c6b5f4 (void at 0x02d56a60)>)

印刷精美

  1. Gtk.LinkButton
  2. Gdk.EventButton

漂亮的打印比较

第一种情况的参数:

  1. Gtk.EventBox
  2. Gtk.EventButton
  3. Gtk.LinkButton

第二种情况的参数:

  1. Gtk.LinkButton
  2. Gdk.EventButton

我想了解这两种情况下输出差异背后的原因。

我在 Windows10 上的 MSYS2 上使用 Python 2.7.13 和 GTK+ 3.22。MSYS2 和 Windows 都安装了所有可用更新。

第二个 glade 文件对 signal 元素有一个 object 属性,相当于在 C 中使用 g_signal_connect_object() 而不是 g_signal_connect()。它通过给定对象(link 按钮)作为信号处理程序的第一个参数。