Диалог прерывается при использовании GtkBuilder для автоматического подключения сигналов, но работает при ручном подключении сигналов

Я хочу иметь диалоговое окно, в котором одни кнопки закрывают диалог, а другие нет. Я делаю это, используя сигнал response от Gtk.Dialog для вызова 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)

затем он начинает работать как задумано (кнопка «Не закрывать диалог» не закрывает диалог).

Но разве эти две строки не должны быть функционально идентичными в этом контексте? Есть ли способ выяснить, чем отличаются эти два сценария?

Я могу сказать, что сигналы все еще связаны в обеих ситуациях, потому что текст все еще печатается в CLI из DummyDialog.on_response. Но похоже, что часть widget.emit_stop_by_name('response') перестает работать, когда я использую GtkBuilder.

Еще большее недоумение вызывает то, что если вы возьмете именно этот код и запустите его на PyGTK (измените from gi.repository import Gtk на import gtk as Gtk), то он будет корректно работать в обоих сценариях (используя self.builder.connect_signals(self) или self.dialog1.connect('response', self.on_response)).


person dumbmatter    schedule 30.01.2012    source источник


Ответы (1)


Я бы сделал немного иначе. Удалите dialog1.destroy() в обратном вызове при нажатии кнопки и измените обратный вызов on_response на:

    def on_response(self, widget, response, data=None):
        print 'response:', response
        if response < 0:
            self.dialog1.destroy()
person Timo    schedule 05.03.2012
comment
Спасибо, это кажется более элегантным решением, чем просто ручное подключение сигналов, которые не работают, что было моим предыдущим решением. Но я все еще недоумеваю, почему мой исходный код не работает. - person dumbmatter; 06.03.2012