2012-01-30 3 views
6

Desidero avere una finestra di dialogo in cui alcuni pulsanti chiudono la finestra di dialogo e altri no. Il modo in cui lo faccio è utilizzando il segnale response da Gtk.Dialog per chiamare emit_stop_by_name('response') nella finestra di dialogo. (Se qualcuno conosce un modo migliore per farlo, ciò potrebbe anticipare l'intero resto della domanda.)La finestra di dialogo si interrompe quando si utilizza GtkBuilder per connettere automaticamente i segnali, ma funziona quando si collegano manualmente i segnali

Questo ha funzionato quando ho usato PyGTK. Mi sto trasferendo a PyGObject ora .. e sembra che questa tecnica funzionerà solo se mi collego manualmente al segnale di risposta anziché utilizzare Gtk.Builder.connect_signals().

Ma non credetemi. Ecco un esempio minimo del mio 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() 

Quando si esegue questo, si ottiene una finestra con un solo pulsante. Quando si fa clic su quel pulsante, viene visualizzata una finestra di dialogo con due pulsanti, uno con l'etichetta "Chiudi finestra di dialogo" e un altro con l'etichetta "Chiudi finestra di dialogo". Quando si esegue il codice sopra, entrambi i pulsanti chiuderanno la finestra di dialogo.

Ma se si passa da utilizzare Gtk.Builder.connect_signals() di collegare manualmente il segnale sostituendo

 self.builder.connect_signals(self) 

con

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

allora inizia a lavorare come progettato (il "non chiudere Dialog" pulsante doesn chiudere la finestra di dialogo).

Ma non dovrebbero quelle due righe essere esattamente funzionalmente identico in questo contesto? C'è un modo per capire cosa c'è di diverso tra i due scenari?

Posso dire che i segnali sono ancora collegati in entrambe le situazioni perché il testo è ancora stampato sulla CLI da DummyDialog.on_response. Ma sembra che la parte widget.emit_stop_by_name('response') smetta di funzionare quando utilizzo GtkBuilder.

Ancora più sconcertante è che se si prende questo codice esatto ed esegue su PyGTK (cambiamento from gi.repository import Gtk-import gtk as Gtk), allora funziona correttamente in entrambi gli scenari (utilizzando self.builder.connect_signals(self) o self.dialog1.connect('response', self.on_response)).

risposta

2

Lo farei un po 'diverso. Rimuovere il dialog1.destroy() nel pulsante cliccato callback e modificare il on_response callback:

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

Grazie, che sembra una soluzione più elegante di segnali di collegamento solo manualmente che non funzionano, che era stata la mia soluzione precedente. Ma sono ancora perplesso sul motivo per cui il mio codice originale non funziona. – dumbmatter