2012-01-30 15 views
6

Quiero tener una ventana de diálogo donde algunos botones cierran el cuadro de diálogo y otros no. La forma en que hago esto es usando la señal response del Gtk.Dialog para llamar al emit_stop_by_name('response') en el cuadro de diálogo. (Si alguien sabe de una mejor manera de hacer esto, eso podría anticiparse al resto de esta pregunta.)El cuadro de diálogo se rompe cuando se usa GtkBuilder para conectar señales automáticamente, pero funciona cuando se conectan manualmente las señales

Esto funcionó cuando utilicé PyGTK. Me estoy moviendo a PyGObject ahora ... y parece que esta técnica funcionará solo si me conecto manualmente a la señal de respuesta en lugar de usar Gtk.Builder.connect_signals().

Pero no confíe en mi palabra. Aquí hay un ejemplo mínimo de mi problema:

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

Cuando ejecuta esto, obtiene una ventana con un solo botón. Cuando hace clic en ese botón, aparece un cuadro de diálogo con dos botones, uno con la etiqueta "No cerrar cuadro de diálogo" y otro con la etiqueta "Cerrar cuadro de diálogo". Al ejecutar el código anterior, ambos botones cerrarán el cuadro de diálogo.

Pero si cambia el uso de Gtk.Builder.connect_signals() a conectar manualmente la señal mediante la sustitución de

 self.builder.connect_signals(self) 

con

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

entonces que empiece a funcionar como fue diseñado (el "No cierre de diálogo" botón doesn cerrar el diálogo).

¿Pero no deberían esas dos líneas ser exactamente idénticas funcionalmente en este contexto? ¿Hay alguna manera de descubrir qué es diferente entre los dos escenarios?

Puedo decir que las señales todavía están conectadas en ambas situaciones porque el texto todavía se imprime en la CLI desde DummyDialog.on_response. Pero parece que la parte widget.emit_stop_by_name('response') deja de funcionar cuando uso GtkBuilder.

Aún más sorprendente es que si se toma el código exacto y ejecutarlo en PyGTK (modificar from gi.repository import Gtk-import gtk as Gtk), entonces funciona correctamente en ambos escenarios (utilizando self.builder.connect_signals(self) o self.dialog1.connect('response', self.on_response)).

Respuesta

2

Lo haría un poco diferente. Retire el dialog1.destroy() en el botón de devolución de llamada hace clic y cambiar la devolución de llamada a on_response:

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

Gracias, que parece una solución más elegante que acaba de señales de conexión manualmente que no funcionan, que había sido mi solución anterior. Pero todavía estoy perplejo sobre por qué mi código original no funciona. – dumbmatter

Cuestiones relacionadas