j'assigne un objet de classe StringVar() à self.text, j'utilises le setter de StringVar() sur self.text et j'assigne self.text à un objet de la classe ttk.Label nommé grossièrement label
Alors j'ai testé text="du texte" à la place de textvariable=self.text et mon label s'affiche, le problème provient donc soit de la classe StringVar(), soit de son setter.
Comment est-ce que je fais pour assigner une string à StringVar()?
ça fonctionne chez moi et ça devrait aussi fonctionner chez vous.
Si tel est le cas, le problème est ailleurs.
ligne 23, ajoutez une référence à l'instance (via xx = tkinterWidget(root)) et tenez compte de la durée de vie des objets utilisés...
- Edité par mps il y a environ 1 heure
J'ai rajouté une référence à l'instance et ça fonctionne comme il faut, cependant je ne saisi pas du tout la logique derrière.
2 questions:
-Qu'est ce que tu entends par "la durée de vie des objets utilisés" ?
-Je suis parti d'un tutoriel qui utilise StringVar() (ligne 12 et 13 ci-dessous) et qui assigne l'objet à textvariable par le biais d'un entry. Dans ce contexte là, pas besoin d'ajouter une réference à l'instance tkinter(root), pourquoi?
Je suis parti d'un tutoriel qui utilise StringVar() (ligne 12 et 13 ci-dessous) et qui assigne l'objet à textvariable par le biais d'un entry. Dans ce contexte là, pas besoin d'ajouter une réference à l'instance tkinter(root), pourquoi?
Mettez en commentaire les lignes qui font référence à la méthode calculate
Normalement, on devrait reproduire le même problème car l'instance de FeetToMeters n'est plus référencée (indirectement)... et les StringVar seront détruits avec l'instance.
C'est une programmation "naïve" qui fonctionne par hasard: changez de tuto!
Une solution simple serait de faire hériter FeetToMeters de tk.Frame. Devenant widget, les références sont gérées par tkinter et l'objet ne sera détruit que via un destroy explicite.
On explicite bien le nom des arguments, ça aide à connaître ceux à quoi les objets font références.
Pas d'espace dans les options, merci !
Dans le dernier code, attention sur la fonction calculate, car si on rentre dans le except, on retourne la valeur None, valeur peut-être pas attendue...
À mon sens, ton deuxième code ne prend pas en compte les remarques relevées par @mps et moi-même, ce que je te conseillerai d'appliquer pour éviter une construction difficile par la suite.
- Edité par fred1599 16 décembre 2023 à 14:26:10
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Si je déplace juste root.mainloop() dans la classe, je vois l'écriture dans le Label.
C'est une astuce qui empêche __init__ de se terminer (bloqué dans mainloop) et... la destruction de l'instance (et des StringVar).
Ça fonctionne comme les références à la méthode calculate dans le code du tuto: un heureux hasard.
Il n'y a rien d'erroné à programmer ainsi. Juste que si ça se casse la gueule quand on bouge une ligne sans que le soucis saute aux yeux, je préfèrerai une construction plus robuste (mais certains aiment ces codes malicieux).
Tout à fait, je conseille... et un conseil n'est pas imposer quoi que se soit, mais écouter l'expérience peut être chose intéressante
- Edité par fred1599 16 décembre 2023 à 15:03:41
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Je suis parti d'un tutoriel qui utilise StringVar() (ligne 12 et 13 ci-dessous) et qui assigne l'objet à textvariable par le biais d'un entry. Dans ce contexte là, pas besoin d'ajouter une réference à l'instance tkinter(root), pourquoi?
Mettez en commentaire les lignes qui font référence à la méthode calculate
Normalement, on devrait reproduire le même problème car l'instance de FeetToMeters n'est plus référencée (indirectement)... et les StringVar seront détruits avec l'instance.
C'est une programmation "naïve" qui fonctionne par hasard: changez de tuto!
Une solution simple serait de faire hériter FeetToMeters de tk.Frame. Devenant widget, les références sont gérées par tkinter et l'objet ne sera détruit que via un destroy explicite.
- Edité par mps 16 décembre 2023 à 7:34:24
Désolé, j'ai du changer de pc entre temps, je viens tout juste de voir ces messages !
Si je comprends bien, en python, la création d'une méthode de classe crée une référence à l'instance ?
L'instance d'une classe est self, les méthodes de classes prennent en argument self qui est une référence de l'objet créé (instance).
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Si je comprends bien, en python, la création d'une méthode de classe crée une référence à l'instance ?
L'existence de la méthode calculate permet de fabriquer l'objet self.calculate et y faire référence dans des instructions comme root.bind(..., self.calculate). Et comme c'est une méthode, c'est une référence a l'objet self et une référence à la fonction calculate (qui sera référencé aussi dans le dictionnaire de la class).
Mettre en commentaire cette instruction supprime ces 2 références (il y en a une autre ligne 18)... et sans référence à self, le StringVar disparait aussi.
Pourquoi changer de tuto? Dans votre exemple, si on ne stocke pas l'instance dans une variable, le garbage collector voit le nombre de références passer à 0 et fait immédiatement le ménage.
Dans l'exemple du tuto, on crée des références circulaires qui font que le nombre de références ne passera pas à 0... Le garbage collector devra examiner la collection des objets alloués pour se rendre compte qu'il peut détruire l'instance.
Le problème sera visible ou pas mais c'est une bombe qui fait tic tac...
Si je comprends bien, en python, la création d'une méthode de classe crée une référence à l'instance ?
L'existence de la méthode calculate permet de fabriquer l'objet self.calculate et y faire référence dans des instructions comme root.bind(..., self.calculate). Et comme c'est une méthode, c'est une référence a l'objet self et une référence à la fonction calculate (qui sera référencé aussi dans le dictionnaire de la class).
Mettre en commentaire cette instruction supprime ces 2 références (il y en a une autre ligne 18)... et sans référence à self, le StringVar disparait aussi.
fred1599 a écrit:
L'instance d'une classe est self, les méthodes de classes prennent en argument self qui est une référence de l'objet créé (instance).
Merci pour vos réponses !
Dans ce cas, histoire de voir si j'ai bien compris: Supposons qu'on supprime def calculate... Ligne 17: on a une référence a self, mais comme aucun objet n'est crée que ce soit par l'instanciation d'un objet de la classe: tk = FeetToMeters(root) qui crée une référence à l'objet self ou par la définition d'une méthode qui crée l'objet self.calculate la référence est caduque et tout ce qui est déclaré de l'objet 'self' disparaît ?
Si la création de l'instance est appelée (FeetToMeters(root)), un mécanisme permettra d'utiliser self en ce qui concerne les méthodes appelées à l'intérieur de la classe. Cependant, si vous ne gardez pas en mémoire l'instance créée, il n'y a pas la possibilité d'utiliser/appeler vos méthodes à l'extérieur de votre classe.
- Edité par fred1599 29 décembre 2023 à 18:56:15
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard) La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Si la création de l'instance est appelée (FeetToMeters(root)), un mécanisme permettra d'utiliser self en ce qui concerne les méthodes appelées à l'intérieur de la classe. Cependant, si vous ne gardez pas en mémoire l'instance créée, il n'y a pas la possibilité d'utiliser/appeler vos méthodes à l'extérieur de votre classe.
le self.a = self crée la référence à l'instance qui fera que le nombre de référence ne passe pas à zéro "tout seul".... Et afficher "del" a ce moment là.
La fonction f est là pour éviter que l'interpréteur "tienne" la référence à l'instance (dans _).
Essayons:
>>> f()
>>> a = A()
>>> del a
>>>
rien... Par contre, si on force le garbage collector pour faire le ménage:
>>> gc.collect()
del
del
2
on voit les 2 "del" apparaître.
Changeons le code pour avoir:
class A:
def __init__(self):
self.a = self
def __del__(self):
print('del')
maintenant on obtient:
>>> f()
del
>>> a = A()
>>> del a
del
>>>
pas besoin de forcer gc.collect pour que l'instance soit détruite.
le self.a = self crée la référence à l'instance qui fera que le nombre de référence ne passe pas à zéro "tout seul".... Et afficher "del" a ce moment là.
La fonction f est là pour éviter que l'interpréteur "tienne" la référence à l'instance (dans _).
Essayons:
>>> f()
>>> a = A()
>>> del a
>>>
rien... Par contre, si on force le garbage collector pour faire le ménage:
>>> gc.collect()
del
del
2
on voit les 2 "del" apparaître.
Changeons le code pour avoir:
class A:
def __init__(self):
self.a = self
def __del__(self):
print('del')
maintenant on obtient:
>>> f()
del
>>> a = A()
>>> del a
del
>>>
pas besoin de forcer gc.collect pour que l'instance soit détruite. Edité par mps il y a environ 23 heures
Dans ce cas est-ce que je me trompe si je dis: Toute réference à une instance dans "_" se verra supprimé à la fin de l'execution d'__init__ et pour résoudre le problème d'une façon explicitée et lisible, il suffit d'ajouter une référence à la classe lors de son appel? Edit: Jreprends mon code tkinter, je rajoute ta fonction __del__ et je vois ce qu'il se passe
Dans ce cas est-ce que je me trompe si je dis: Toute réference à une instance dans "_" se verra supprimé à...
_ n'a de sens que dans l'interpréteur interactif (lorsqu'on exécute normalement un script, cette variable n'existe pas).
Pour ce qui est de résoudre le problème initial, faire hériter FeetToMeters de Frame est le plus "naturel" (ça devient widget). Dans ce cas, inutile de garder une référence à l'instance: tkinter le fait déjà.
- Edité par mps 31 décembre 2023 à 18:12:23
set() de StringVar() qui ne fonctionne pas?
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)
Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)