2012-01-30 8 views
6

Chcę mieć okno dialogowe, w którym niektóre przyciski zamykają okno, a inne nie. Sposób, w jaki to robię, polega na użyciu response sygnału z Gtk.Dialog w celu wywołania emit_stop_by_name('response') w oknie dialogowym. (Jeśli ktoś zna lepszy sposób na zrobienie tego, może to przejąć całą resztę tego pytania.)Przerwanie dialogowe podczas używania GtkBuilder do automatycznego łączenia sygnałów, ale działa przy ręcznym podłączaniu sygnałów.

To działało, gdy użyłem PyGTK. Przechodzę teraz do PyGObject ... i wygląda na to, że ta technika zadziała tylko wtedy, gdy ręcznie połączę się z sygnałem odpowiedzi, zamiast używać Gtk.Builder.connect_signals().

Ale nie wierz mi na słowo. Oto minimalny przykład mojego problemu:

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

Po uruchomieniu otrzymasz okno z jednym przyciskiem. Po kliknięciu tego przycisku pojawi się okno dialogowe z dwoma przyciskami, jeden z napisem "Nie zamykaj okna dialogowego", a drugi z etykietą "Zamknij okno dialogowe". Po uruchomieniu powyższego kodu oba przyciski zamkną okno dialogowe.

Ale jeśli zmieni się z użyciem Gtk.Builder.connect_signals() ręcznego podłączania sygnału zastępując

 self.builder.connect_signals(self) 

z

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

następnie zaczyna działać zgodnie z przeznaczeniem (dalej „Nie zamykaj Dialog” przycisk robi zamknij okno dialogowe).

Ale czy te dwie linie nie powinny być dokładnie identyczne pod względem funkcjonalności? w tym kontekście? Czy jest jakiś sposób, aby dowiedzieć się, co różni się między tymi dwoma scenariuszami?

Mogę powiedzieć, że sygnały są nadal połączone w obu sytuacjach, ponieważ tekst jest nadal drukowany w CLI z DummyDialog.on_response. Ale wydaje się, że część widget.emit_stop_by_name('response') przestaje działać, gdy używam GtkBuilder.

Jeszcze bardziej kłopotliwy jest to, że jeśli wziąć dokładnie ten kod i uruchomić go na PyGTK (zmiana from gi.repository import Gtk do import gtk as Gtk), to działa poprawnie w obu przypadkach (przy użyciu self.builder.connect_signals(self) lub self.dialog1.connect('response', self.on_response)).

Odpowiedz

2

Zrobiłbym to trochę inaczej. Usunąć dialog1.destroy() w przycisk kliknięciu zwrotnego i zmienić on_response oddzwanianie do:

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

Dzięki, że wydaje się być bardziej eleganckie rozwiązanie niż tylko ręcznie łączących sygnałów, które nie działają, który był moim poprzednie rozwiązanie. Ale wciąż jestem zakłopotany, dlaczego mój oryginalny kod nie działa. – dumbmatter

Powiązane problemy