OVH Cloud OVH Cloud

[wxpython] problème avec les barres de progressions

5 réponses
Avatar
Jerome
Bonjour

Un problème avant le week-end...


Soit le programme

import wx

class Win(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
s=wx.BoxSizer(wx.VERTICAL)
self.gauge = wx.Gauge(self, -1, 100)
b = wx.Button(self, wx.ID_OK)
self.Bind(wx.EVT_BUTTON, self.OnOk, b)
s.AddMany([self.gauge,b])
self.SetSizerAndFit(s)
self.Show(True)

def OnOk(self, evt):
for i in range(100):
for t in range(10000):
t=t*222**0.89
print i
self.gauge.SetValue(i)

app = wx.PySimpleApp()
frame=Win()
app.MainLoop()

Lorsque je l'exécute (un clique sur le bouton ok), la ligne de commande
m'affiche progressivement les print i. Mais la "gauge" elle ne se met à
jour qu'à la fin de la boucle sur i... Elle passe de 0 à 100
instantanément. Qu'est-ce que je fais mal ? Je ne dois quand même pas
lancer un thread pour faire ça ?


Merci,
Jérôme

5 réponses

Avatar
tiissa

Lorsque je l'exécute (un clique sur le bouton ok), la ligne de commande
m'affiche progressivement les print i. Mais la "gauge" elle ne se met à
jour qu'à la fin de la boucle sur i... Elle passe de 0 à 100
instantanément. Qu'est-ce que je fais mal ? Je ne dois quand même pas
lancer un thread pour faire ça ?


Je ne connais pas wxPython mais, en general, lorsque c'est un probleme
de mise-a-jour, une solution est de lui demander de redessiner.

Apres un petit tour sur la doc, self.gauge.Refresh() apres
l'incrementation semblerait faire l'affaire.

Ensuite il faut voir si on veut vraiment la redessiner apres chaque
calcul ou seulement a une frequence fixee. Dans ce cas, il y a surement
la possibilite de mettre en place un alarme pour executer une fonction
regulierement.

Avatar
fraca7

def OnOk(self, evt):
for i in range(100):
for t in range(10000):
t=t*222**0.89
print i
self.gauge.SetValue(i)


Pendant qu'on est là-dedans, on ne passe pas par la boucle d'évènements
de wx, alors il ne risque pas de se passer quoi que ce soit...

Il faut soit faire ça dans un thread soit utiliser un wx.Timer pour
incrémenter la valeur à intervalles réguliers.

Avatar
Jerome
fraca7 wrote:

def OnOk(self, evt):
for i in range(100):
for t in range(10000):
t=t*222**0.89
print i
self.gauge.SetValue(i)



Pendant qu'on est là-dedans, on ne passe pas par la boucle d'évènements
de wx, alors il ne risque pas de se passer quoi que ce soit...

Il faut soit faire ça dans un thread soit utiliser un wx.Timer pour
incrémenter la valeur à intervalles réguliers.


Ca me semblait normal, dans un environnement objet, que la modification
de la valeur d'un widget génère un événement pour qu'il actualise son
affichage. Apparement ça ne le fait pas.

Par contre, le code que j'ai posté fonctionne sous windows :-(


Avatar
Jerome
wrote:


Lorsque je l'exécute (un clique sur le bouton ok), la ligne de commande
m'affiche progressivement les print i. Mais la "gauge" elle ne se met à
jour qu'à la fin de la boucle sur i... Elle passe de 0 à 100
instantanément. Qu'est-ce que je fais mal ? Je ne dois quand même pas
lancer un thread pour faire ça ?



Je ne connais pas wxPython mais, en general, lorsque c'est un probleme
de mise-a-jour, une solution est de lui demander de redessiner.

Apres un petit tour sur la doc, self.gauge.Refresh() apres
l'incrementation semblerait faire l'affaire.



Sous linux ça ne suffit pas...

Ensuite il faut voir si on veut vraiment la redessiner apres chaque
calcul ou seulement a une frequence fixee. Dans ce cas, il y a surement
la possibilite de mettre en place un alarme pour executer une fonction
regulierement.


oui, bien entendu ;-) Le code que j'ai posté est le code minimal que
j'ai écrit pour démontrer le fonctionnement qui me semble anormal...


Avatar
fraca7
fraca7 wrote:


Pendant qu'on est là-dedans, on ne passe pas par la boucle
d'évènements de wx, alors il ne risque pas de se passer quoi que ce
soit...

Il faut soit faire ça dans un thread soit utiliser un wx.Timer pour
incrémenter la valeur à intervalles réguliers.


Ca me semblait normal, dans un environnement objet, que la modification
de la valeur d'un widget génère un événement pour qu'il actualise son
affichage. Apparement ça ne le fait pas.


Certes, les évènements sont 'générés', ie les messages sont postés dans
la queue de message du thread principal, mais si celui-ci ne retourne
pas dans la boucle d'évènement pour les gérer, ils n'ont aucun effet. En
théorie.

Par contre, le code que j'ai posté fonctionne sous windows :-(


Effectivement. C'est louche. La méthode SetValue doit 'forcer' le
traitement des messages dans wxMSW mais pas dans wxGTK... Il faudrait
jeter un coup d'oeil au source pour être sûr...

Enfin, de toutes façons je pense que c'est toujours une mauvaise idée de
faire un traitement de longue haleine dans le thread principal d'un GUI.