Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

gtk et threads sous windows

3 réponses
Avatar
Jonathan Barnoud
L'utilisation de thread avec n'impporte quel toolkit graphique semble
poser beaucoup de problème.

J'utilise gtk depuis récemment (quelques nuits tout au plus) et je suis
parvenu à faire une appli avec des threads. Chouette. Sauf que voila,
l'appli tourne au poil sous linux mais pose problème sous windows.

Lancée tel quel, la fenêtre s'affiche, il y a le cadre des widget (un
rectangle blanc pour les treeview et autres entry par enxemple) mais
l'appli freeze.

Le problème semble venir de gtk.gdk.threads_init() puisque, lorsque je
commente la dite ligne, la fenêtre apprait toute bien avec tous ses
widgets. Bien sur, sans cette ligne, les threads ont un fonctionnement
très sporadique voire quasiment inexistant. En tout cas pas utilisable.

J'ai essayé de faire un petit programme qui reproduit le problème :

##########################################

#!/usr/bin/env python
#_*_ coding:utf-8 _*_

import gtk
import time
from threading import Thread

class MonThread(Thread) :
def __init__(self, widget, begin) :
Thread.__init__(self)
self.go = False
self.widget = widget
self.begin = begin
def run(self) :
self.go = True
self.i = self.begin
while self.go :
gtk.gdk.threads_enter()
self.widget.set_label("On en est à %i monton%s" % \
(self.i, "s"*(self.i>1)))
gtk.gdk.threads_leave()
time.sleep(1)
self.i+=1
def stop(self) :
self.go = False
return self.i

class Base :
def __init__(self):
self.fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.fenetre.connect("delete_event", self.evnmt_delete)
self.fenetre.connect("destroy", self.destroy)

self.bouton = gtk.Button("J'aime compter les moutons !")
self.bouton.connect_object("clicked", self.clik, None)
self.fenetre.add(self.bouton)
self.moutons_run = MonThread(self.bouton, 0)

self.infobulles = gtk.Tooltips()
info_text = "Cliquez ici pour compter les moutons."
self.infobulles.set_tip(self.bouton, info_text, tip_private=None)

self.bouton.show()
self.fenetre.show()

def evnmt_delete(self, widget, event, donnees=None):
return False

def destroy(self, widget, donnees=None):
gtk.main_quit()

def clik(self, event, donnees=None) :
if not self.moutons_run.go :
self.moutons_run.start()
self.infobulles.set_tip(self.bouton, "Ne plus compter.",
tip_private=None)
else :
i = self.moutons_run.stop()
self.moutons_run = MonThread(self.bouton, i)
self.infobulles.set_tip(self.bouton, "Compter de nouveau.",
tip_private=None)

Base()
gtk.gdk.threads_init()
gtk.main()


##########################

Sous linux ça compte bien les moutons mais pas sous windows.

Si quelqu'un a une solution ou même une piste je suis preneur.

Merci

--
Jonathan Barnoud
http://pititjo.net

3 réponses

Avatar
hg
Jonathan Barnoud wrote:

##########################################

#!/usr/bin/env python
#_*_ coding:utf-8 _*_

import gtk
import time
from threading import Thread

class MonThread(Thread) :
def __init__(self, widget, begin) :
Thread.__init__(self)
self.go = False
self.widget = widget
self.begin = begin
def run(self) :
self.go = True
self.i = self.begin
while self.go :
gtk.gdk.threads_enter()
self.widget.set_label("On en est à %i monton%s" %
(self.i, "s"*(self.i>1)))
gtk.gdk.threads_leave()
time.sleep(1)
self.i+=1
def stop(self) :
self.go = False
return self.i

class Base :
def __init__(self):
self.fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.fenetre.connect("delete_event", self.evnmt_delete)
self.fenetre.connect("destroy", self.destroy)

self.bouton = gtk.Button("J'aime compter les moutons !")
self.bouton.connect_object("clicked", self.clik, None)
self.fenetre.add(self.bouton)
self.moutons_run = MonThread(self.bouton, 0)

self.infobulles = gtk.Tooltips()
info_text = "Cliquez ici pour compter les moutons."
self.infobulles.set_tip(self.bouton, info_text, tip_private=None)

self.bouton.show()
self.fenetre.show()

def evnmt_delete(self, widget, event, donnees=None):
return False

def destroy(self, widget, donnees=None):
gtk.main_quit()

def clik(self, event, donnees=None) :
if not self.moutons_run.go :
self.moutons_run.start()
self.infobulles.set_tip(self.bouton, "Ne plus compter.",
tip_private=None)
else :
i = self.moutons_run.stop()
self.moutons_run = MonThread(self.bouton, i)
self.infobulles.set_tip(self.bouton, "Compter de nouveau.",
tip_private=None)

Base()
gtk.gdk.threads_init()
gtk.main()


Il me semble avoir eu un problème équivalent il y a plusieurs années .... en
C: Je te conseille de lire les FAQs de GTK+ à ce sujet
(http://www.gtk.org/faq/#AEN482 section 5.2)

M'est avis que "potentiellement":
1) c'est pas un problème lié à Python mais juste l'utilisation de GTK+
2) c'est peut être un hazard si marche sous *nix

J'écris maintenant des applis cross-plateformes depuis pas mal d'années ...
et j'utilise toujours Windows pour trouver mes bugs ... ils apparaissent
toujours sur Windows d'abords.

hg

Avatar
hg
hg wrote:

Jonathan Barnoud wrote:

##########################################

#!/usr/bin/env python
#_*_ coding:utf-8 _*_

import gtk
import time
from threading import Thread

class MonThread(Thread) :
def __init__(self, widget, begin) :
Thread.__init__(self)
self.go = False
self.widget = widget
self.begin = begin
def run(self) :
self.go = True
self.i = self.begin
while self.go :
gtk.gdk.threads_enter()
self.widget.set_label("On en est à %i monton%s" %
(self.i, "s"*(self.i>1)))
gtk.gdk.threads_leave()
time.sleep(1)
self.i+=1
def stop(self) :
self.go = False
return self.i

class Base :
def __init__(self):
self.fenetre = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.fenetre.connect("delete_event", self.evnmt_delete)
self.fenetre.connect("destroy", self.destroy)

self.bouton = gtk.Button("J'aime compter les moutons !")
self.bouton.connect_object("clicked", self.clik, None)
self.fenetre.add(self.bouton)
self.moutons_run = MonThread(self.bouton, 0)

self.infobulles = gtk.Tooltips()
info_text = "Cliquez ici pour compter les moutons."
self.infobulles.set_tip(self.bouton, info_text, tip_private=None)

self.bouton.show()
self.fenetre.show()

def evnmt_delete(self, widget, event, donnees=None):
return False

def destroy(self, widget, donnees=None):
gtk.main_quit()

def clik(self, event, donnees=None) :
if not self.moutons_run.go :
self.moutons_run.start()
self.infobulles.set_tip(self.bouton, "Ne plus compter.",
tip_private=None)
else :
i = self.moutons_run.stop()
self.moutons_run = MonThread(self.bouton, i)
self.infobulles.set_tip(self.bouton, "Compter de nouveau.",
tip_private=None)

Base()
gtk.gdk.threads_init()
gtk.main()


Il me semble avoir eu un problème équivalent il y a plusieurs années ....
en C: Je te conseille de lire les FAQs de GTK+ à ce sujet
(http://www.gtk.org/faq/#AEN482 section 5.2)

M'est avis que "potentiellement":
1) c'est pas un problème lié à Python mais juste l'utilisation de GTK+
2) c'est peut être un hazard si marche sous *nix

J'écris maintenant des applis cross-plateformes depuis pas mal d'années
... et j'utilise toujours Windows pour trouver mes bugs ... ils
apparaissent toujours sur Windows d'abords.

hg


PS: note aussi ... je sais pas si gtk.gdk.threads_init() fait les deux

/* init threads */
g_thread_init(NULL);
gdk_threads_init();


Avatar
Jonathan Barnoud

Il me semble avoir eu un problème équivalent il y a plusieurs années .... en
C: Je te conseille de lire les FAQs de GTK+ à ce sujet
(http://www.gtk.org/faq/#AEN482 section 5.2)


Pour info, la FAQ de pygtk :
<http://www.async.com.br/faq/pygtk/index.py?req=index>
Et la page qui répond à ma question et que je n'avait pas vue :
<http://www.async.com.br/faq/pygtk/index.py?req=show&fileúq20.006.htp>


M'est avis que "potentiellement":
1) c'est pas un problème lié à Python mais juste l'utilisation de GTK+
2) c'est peut être un hazard si marche sous *nix


Effectivement, mon problème était lié à une mauvaise utilisation de GTK
et c'était un hazard si ça marchait sous linux.

Si j'ai bien compri, gtk.gdk.threads_* se comporte comme un sémaphore,
threads_init() l'initie et le bloque, threads_enter() l'ouvre,
threads_leave() le ferme à nouveau.
Sous linux, l'initialisation laisse peut-être le sémaphore ouvert, ce
qui expliquerait que ça marchait.

La solution à mon problème était :

gtk.gdk.threads_init()
gtk.gdk.threads_enter()
gtk.main()
gkt.gdk.threads_leave()

au lieu de juste :

gtk.gdk.threads_init()
gtk.main()


J'écris maintenant des applis cross-plateformes depuis pas mal d'années ...
et j'utilise toujours Windows pour trouver mes bugs ... ils apparaissent
toujours sur Windows d'abords.


Oui mais je limite le plus possible le reboot sous windows.


hg



Merci pour votre aide.

--
Jonathan Barnoud
http://pititjo.net