Newsgroup: it.comp.os.linux.development
Titolo: Python glade GTK e finestre multiple.

Per la mia applicazione ho bisogno di utilizzare più finestre. In
particolare all'attivazione di una voce di un menù devo aprire la
seconda finestra. Come vedete dal subj, per l'interfaccia ho usato Glade
e poi carico a runtime l'interfaccia con libglade.
L'interfaccia la carico tutta in una volta (anche la window2 quindi),
per default ho fatto in modo che la window2 sia hide, salvo poi
richiamare window2.show() quando questa deve essere mostrata, ho anche
colleggato il metodo legato alla distruzione della finestra e ho fatto
in modo che la finestra venga nuovamente nascosta. La prima volta tutto
funziona, ma se cerco di aprire nuovamente la finestra questa non si
apre correttamente, mi appare l'errore:
Gtk-CRITICAL **: file gtkstyle.c: line 513 (gtk_style_attach): assertion
`style != NULL' failed.
Gtk-CRITICAL **: file gtkstyle.c: line 1134 (gtk_style_set_background):
assertion `style != NULL' failed.
Gtk-CRITICAL **: file gtkstyle.c: line 3613 (gtk_paint_flat_box):
assertion `style != NULL' failed.
e si apre una finestra piccola e tutta nera :-/
Riporto il codice interessato:
#Questa è la callback dell'attivazione del menu, mostra la window2
def on_lista_gruppi1_activate (obj):
    "Mostra la finestra con la lista dei gruppi."
    print "lista gruppi1 activate"
    window2.show()
 
#Questa è la callback collegata alla distruzione della window2
def on_window2_destroy(obj):
    "Metodo richiamato alla distruzione della window2"
    print "win2 destroy"
    window2.hide()
    return 1
#Segue il codice con il quale mi carico a runtime l'interfaccia fatta
#con Glade
interface = GladeXML ("newsx.glade")
#Questo dic contiene la lista delle callback collegate ai vari segnali
dic ={"on_lista_gruppi1_activate":on_lista_gruppi1_activate,
      "on_window1_destroy":mainquit,
      "on_window2_show":on_window2_show,
      "on_button1_clicked":on_button1_clicked,
      "on_button2_clicked":on_button2_clicked,
      "on_button5_clicked":on_button5_clicked,
      "on_clist2_select_row":on_clist2_select_row,
      "on_clist3_select_row":on_clist3_select_row,
      "on_clist1_select_row":on_clist1_select_row,
      "on_ctree1_select_row":on_ctree1_select_row,
      "on_window2_destroy":on_window2_destroy}
#Connessione delle calllback
interface.signal_autoconnect(dic)
#Con il codice seguente grabbo i riferimenti ai vari widget
window1=interface.get_widget("window1")
window2=interface.get_widget("window2")
Come va gestita correttamente questa situazione??
-- 
 |\ |       <-> 
http://digilander.libero.it/nemesis2001/
 | \|emesis <->      "War, war never change us..."
 

       "on_window2_show":on_window2_show,
Scusa, ma questo che fa?
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! Drink To Your Brothers Who Are Never To Fall, We Are Brothers Of Metal
  		Here In The Hall! !>- Manowar - Brothers Of Metal PT1

 Scusa, ma questo che fa?
Se ti riferisci a quella riga in particolare, serve a comunicare a
libglade quale metodo deve collegare al segnale "on_window2_show"
selezionato tramite Glade.
Se invece ti riferisci al metodo vero e proprio, serve soltanto ad
inizializzare un paio di widget presenti nella finestra, cmq ecco il
codice:
def on_window2_show (obj):
    "Carica la lista dei gruppi disponibili."
    print "window 2 show"
    try:
        out=open("gruppi.txt","r")
    except IOError:
        clist2.append(("unavailable","0"))
    else:
        lista=cPickle.load(out)
        clist2.freeze()
        for i in range(len(lista)):
	    diff=int(lista[i][1])-int(lista[i][2])
	    clist2.append((lista[i][0],repr(diff)))
	clist2.thaw()
        out.close()
    mostra_sottoscritti_win2()
 
def mostra_sottoscritti_win2():
    "Riscrive i gruppi sottoscritti nella finestra 2."
    try:
        sottoscritti=open("sottoscritti.txt","r")
    except IOError:
        clist3.append(["nessun gruppo sottoscritto"])
    else:
        clist3.clear()
        gruppi=cPickle.load(sottoscritti)
        for j in range(len(gruppi)):
            clist3.append([gruppi[j]])


 def mostra_sottoscritti_win2():
...
Orbene: a quanto pare ci sono degli scazzi con la gestione del segnale show
relativo a window2 (o sbaglio?). Il metodo on_window2_show come l'hai
connesso? Con un connect_after? Se no potrebbe essere che, non ritornando 0,
il segnale non viene propagato e l'effettivo show del widget non viene
eseguito.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail** 
       -<! Riding from wastelands Black were their skies
              My armour's still bleeding Ripped by fire and ice !>-
                    Lost Horizon - The Kingdom Of My Will

 eseguito.
No l'ho connesso come tutti gli altri metodi con la chiamata
interface.signal_autoconnection(dic)
dove dic è il dictionary che contiene le corrispondenze segnale:metodo.
Se ho ben capito mi dici di aggiungere un "return 0" alla fine del
metodo "on_window2_show(obj)", beh l'ho fatto, ma non cambia nulla :-/


 metodo "on_window2_show(obj)", beh l'ho fatto, ma non cambia nulla :-/
E se provi a fare uno show_all e a ritornare 1?
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! Battles Are Fought By Those With The Courage To Believe !>-
  		Manowar - Courage

 E se provi a fare uno show_all e a ritornare 1?
Allora, ho cambiato window2.show() in window2.show_all() e aggiunto
return 1 ... niente non va nemmeno così, sempre stesso difetto :-/


 return 1 ... niente non va nemmeno così, sempre stesso difetto :-/
Scusa, ma forse ci siamo persi. Dov'e' che metti window2.show_all()
Quello che dico io e' di metterlo in on_window2_show () e da li' ritornare
1. Poi magari non cambia niente...
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! Take It All, Our Gold, Our Homes, Our Life, But We Didn't Kill 
	    Your Christ! !>- Blind Guardian - The Script For My Requiem

Poi magari non cambia niente...
apputno :-/
cmq io più che qua ho il dubbio che il problema sia nella distruzione.
In pratica io ho collegato il segnale destroy del widget window2 alla
funzione 
def on_window2_destroy ()
    window2.hide()
tuttavia ho l'impressione che la finestra invece di essere nascosta
viene proprio distrutta.


 viene proprio distrutta.
Per quanto ne so io, ed e' poco, se ritorni 1 da un signal handler il
segnale si considera gestito. Per cui non vedo perche' dovrebbe essere di
nuovo propagato.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! Adding features does not necessarily increase functionality -- it just
		makes the manuals thicker. !>-

 di nuovo propagato.
A questo punto (e` da un po' che il thread si propaga, anche su ic.lang,
ho l'impressione che sia un bug della sua versione di pygtk/pygnome.
Nemesis: ci riporti le versioni che stai usando? Di python, pygtk,
pygnome, libgtk, libgnome, ecc.
Bye.

 pygnome, libgtk, libgnome, ecc.
Sono le versioni contenute in Debian Woody, quindi:
Python  2.1.3
Gtk     1.2.10
PyGtk   0.6.9
PyGlade 0.6.9
Glade   0.6.4
Magari qualcuno di voi che utilizza versioni diverse di queste librerie
può dare un'occhiata al codice:
http://digilander.libero.it/nemesis2001/NewsX.html
Lanciate il programma (newsx.py) aprite il primo menu ("server") e richiamate
l'unica voce presente ("Lista Gruppi"), si aprirà la seconda finestra, quella
incriminata, se la chiudete (e sulla console potete leggere "window2 destroy"
a conferma del fatto che il metodo on_window2_destroy viene richiamato) e 
provate a riaprirla si verifica l'errore.


 provate a riaprirla si verifica l'errore.
Probabile che sia un bug davvero. Anche perche' da GGAD
"delete_event", on the other hand, is something of a special case. It
accepts three arguments; the first and last are analagous to "clicked",
while the second is a pointer to the event which triggered the signal
(events are messages from X to the application, reporting mouse movements,
key presses, and the like). The "delete_event" callback returns a "magic"
value---if FALSE is returned, GTK+ will destroy the window; if  TRUE is
returned, GTK+ will do nothing. Return TRUE if you need to do something
other than destroy the window; for example, you might want to warn the user
about an unsaved document. 
quindi ritornando TRUE non dovrebbe fare una grinza, invece la fa eccome.
O il default signal handler viene comunque chiamato oppure e' un problema di
referenze. Come workaround mi viene in mente solo di usare signal_emit_stop
prima di ritornare nel distruttore di win2. Solo che poi non funziona piu'
il pulsante di chiusura nella decorazione. E non so come fare a riabilitare
l'emissione.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! The Moment Is Now In All History, The Time Has Arrived And This Is The
  		One Place To Be. !>- Savatage - This Is The Time

 l'emissione.
Quindi tu ritieni che sia un bug di GTK+?
Magari invece di nascondere e scoprire la finestra dovrei costruirla
ogni volta come nuova, richiamano GladeXML solo per il widget window2,
anche se in questo modo poi non saprei come refenziare i widget della
finestra 2 in tutte le altre funzioni ... hmmm ci devo pensare un pò su.
Però a questo punto mi interesserebbe sapere se qualcuno con versioni
diverse di GTK+ Glade e compagnia bella ha provato il programma ed ha
riscontrato lo stesso problema.


 problema.
L'ho provato anche io con le versioni di sid e fa lo stesso.
Ho l'impressione che vengano persi i riferimenti ai widget contenuti
nella finestra, non tanto la finestra in se, pero` non saprei come
risolvere. Io solitamente programmo a oggetti con pygtk e non mi
succede, quindi penso sia un problema di riferimenti passati da python
in giro per le funzioni.
Bye.

 riscontrato lo stesso problema.
python 2.2.1
pygtk 0.6.11
pygtk-libglade 0.6.11
non va una mazza
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail** 
-<! At first there was nothing. Then God said 'Let there be light!' Then
		there was still nothing. But you could see it. !>-

 in giro per le funzioni.
Ok, grazie lo stesso per il tempo perso :-)


 non va una mazza
Moment, con "non va una mazza" che intendi, non funziona la win2 oppure
non funziona proprio niente, no sai com'è mi puoi far venire un infarto
così :-)


 così :-)
Niente infarti. Non funziona la gestione del segnale destroy come a te. Il
resto mi sembra che vada senza problemi.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! 3rd Law of Computing: Anything that can go wr
		fortune: Segmentation violation -- Core dumped !>-

 resto mi sembra che vada senza problemi.
Meno male :-)
Cmq su comp.lang.python mi hanno consigliato un indirizzo con le faq di
PyGtk nelle quale c'è anche una voce su questo problema, ora ci do
un'occhiata.
Se può interessare a qualcuno il link è:
http://www.async.com.br/faq/pygtk/index.py?req=show&file=faq10.006.htp


 
http://www.async.com.br/faq/pygtk/index.py?req=show&file=faq10.006.htp
Ed in effetti mi ha dato la soluzione, è bastato scollegare il segnale
destroy e collegare al suo posto il delete_event, infatti il primo non
può essere scavalcato col trucchetto del return 1, mentre il
delete_event si.
