2017-10-20 42 views
1

J'ai une petite application graphique en Python qui utilise Tk. Il a plusieurs filtres --- des entrées de texte (ils définissent des valeurs de filtre) avec des cases à cocher (qui activent/désactivent le filtre). Créer des filtres en tant que classe inhetrited de l » Labelframettk:Widgets dépendants dans tkinter

from tkinter.ttk import Labelframe 
import tkinter as tk 

class FilterWidget(Labelframe): 

    def __init__(self, parent, label): 
     Labelframe.__init__(self, parent, text=label) 
     self.grid() 
     self._entry = tk.Entry(self) 
     self._entry.grid(row=0, column=0) 
     self._checkbox = tk.Checkbutton(self, command=lambda: print(self)) 
     self._checkbox.grid(row=0, column=1) 

Puis-je créer plusieurs instances de cette classe et de les placer dans l'interface graphique:

root = tk.Tk() 

source_filter = FilterWidget(root, "Source") 
source_filter.grid(row=0, column=0) 
level_filter = FilterWidget(root, "Severity") 
level_filter.grid(row=0, column=1) 

root.mainloop() 

Les widgets sont créés et affichés correctement. Cependant, quand l'une des cases est cochée et change d'état, l'autre change d'état aussi!

Lorsque vous cliquez sur les différentes cases à cocher, print commande les sorties .!filterwidget et .!filterwidget2, il s'agit donc d'objets distincts. Il semble qu'ils soient en quelque sorte implicitement syncronisés, mais je n'ai aucune idée de comment cela s'est passé. Donc, la question est: comment supprimer cette dépendance et cocher les cases indépendamment les unes des autres?

+0

Je n'obtiens pas le comportement que vous décrivez. Êtes-vous certain que ce code exact présente le problème? –

+0

Oui, deux extraits dans la réponse sont le code complet qui reproduit le problème pour moi. Je cours Python 3.6.2 (v3.6.2: 5fd33b5, 8 juillet 2017, 04:14:34) [MSC v.1900 32 bits (Intel)]) sur Windows 7. – Month

Répondre

2

Comme the docs mention,

Pour utiliser un Checkbutton, vous devez créer une variable Tkinter. Pour inspecter l'état du bouton, interrogez la variable.

Voici votre code mis à jour pour utiliser un IntVar pour stocker l'état Checkbutton.

from tkinter.ttk import Labelframe 
import tkinter as tk 

class FilterWidget(Labelframe): 
    def __init__(self, parent, label): 
     Labelframe.__init__(self, parent, text=label) 
     self._entry = tk.Entry(self) 
     self._entry.grid(row=0, column=0) 

     self._var = tk.IntVar() 
     callback = lambda: print(self._entry.get(), self._var.get()) 
     checkbox = tk.Checkbutton(self, variable=self._var, command=callback) 
     checkbox.grid(row=0, column=1) 

root = tk.Tk() 

source_filter = FilterWidget(root, "Source") 
source_filter.grid(row=0, column=0) 
level_filter = FilterWidget(root, "Severity") 
level_filter.grid(row=0, column=1) 

root.mainloop() 
+0

Oui, cela résout le problème. Je n'ai jamais eu l'intention d'utiliser explicitement la valeur checkbox et je me suis contenté d'un callback, alors j'ai pensé qu'il n'était pas nécessaire d'en créer un. Plus me tromper pour ne pas accorder assez d'attention aux docs. – Month

+0

@Month Ne jamais sous-estimer la capacité de Tkinter à vous dérouter avec ses diverses bizarreries. ;) –