Problème avec customtkinter et son widget button

Résolu/Fermé
pycarpe Messages postés 16 Date d'inscription lundi 24 janvier 2022 Statut Membre Dernière intervention 9 août 2022 - 7 août 2022 à 20:25
 mouette_ombrageuse - 8 août 2022 à 21:54

Hello, 

J'ai l'impression qu'il y a un bug avec customtkinter.CTkButton et son option command. 

Je m'explique, suivant le code ci-dessous si je laisse ce dernier tel quel, rien ne se passe quand je clique sur le bouton test.

Par contre si je remplace customtkinter.CTkButton par Button (Ln84) donc en passant par la librairie tkinter classique, la commande est bien prise en compte. 

C'est un bug? Ou c'est moi qui ai mal compris un truc.

Merci par avance.

from msilib import add_data
from tkinter import *
from tkinter import ttk
import tkinter as tk
import customtkinter


class Widg():

    decal = 0

    def __init__(self, ua, sa, da, ta):
        self.ua = ua
        self.sa = sa
        self.da = da
        self.ta= ta
        self.decal = Widg.decal
        ta ["command"] = self.get_values
        self.ta.place(relx = 0.300, rely = 0.150 + self.decal)
        Widg.decal += 0.05
       
    
    def get_values(self):
        a = self.ua.get()
        b = self.sa.get()
        c = self.da.get()
        print(a,b,c)
    

 



class myApp(tk.Frame):
        def __init__(self, fenetre_principale=None):
            tk.Frame.__init__(self, fenetre_principale)
            self.pack(expand=True, fill="both")
            self.ajout()
            
            
            self.scrollbarx = Scrollbar(self, orient = HORIZONTAL)
            self.scrollbary = Scrollbar(self, orient = VERTICAL)
            self.my_tree = ttk.Treeview(self)
            self.my_tree.place(relx = 0.01, rely = 0.128, width = 646, height = 410)

            self.my_tree.configure(yscrollcommand=self.scrollbary.set, xscrollcommand=self.scrollbarx.set)
            self.my_tree.configure(selectmode="extended")
            self.scrollbary.configure(command = self.my_tree.yview)
            self.scrollbarx.configure(command = self.my_tree.xview)


            self.scrollbary.place(relx = 0.934, rely = 0.128, width = 22, height = 432)
            self.scrollbarx.place(relx = 0.002, rely = 0.922, width = 651, height = 22)



            self.my_tree.configure(columns =("A", "B", "C"))




            self.my_tree.heading("#0", text = "ID", anchor = W)
            self.my_tree.heading("A", text = "A", anchor = W)
            self. my_tree.heading("B", text = "B", anchor = W)
            self.my_tree.heading("C", text = "C", anchor = W)


            self.my_tree.column("#0", stretch = NO, minwidth = 25, width = 125)
            self.my_tree.column("#1", stretch = NO, minwidth = 0, width = 200)
            self.my_tree.column("#2", stretch = NO, minwidth = 0, width = 160)
            self.my_tree.column("#3", stretch = NO, minwidth = 25, width = 160)

            self.id = 0


        def printa(self):
            print(self.u.get(), self.s.get(), self.d.get())


        def add_data(self):

            self.my_tree.insert(parent = '', index = 'end', text = f"0{self.id}", iid = self.id, values = (self.u.get(), self.s.get(), self.d.get()))
            self.id += 1
            self.bu = customtkinter.CTkButton(self, text = "test") ############################################ VOIR CETTE LIGNE ##################################################
            w1 = Widg(self.u, self.s, self.d, self.bu)
            self.u.config(state = "disabled")
            self.s.config(state="disabled")
            self.d.config(state="disabled")
            


        def ajout(self):
            self.buajout = Button(self, text = "New entry", command = self.add_entries).grid(row=1,column=0)
        

        def add_entries(self):
            self.buajout = Button(self, text = "Ajouter", command = self.add_data).grid(row=1,column=2)
            self.u = Entry(self, relief=RIDGE,width=15,bg='white')
            self.u.grid(row=1,column=1)
            self.s = Entry(self, relief=RIDGE,width=15,bg='white')
            self.s.grid(row=2,column=1)
            self.d = Entry(self, relief=RIDGE,width=15,bg='white')
            self.d.grid(row=3,column=1)
            


root = Tk()

root.geometry("1980x720")
app = myApp(fenetre_principale=root)

root.mainloop()

3 réponses

Bonsoir, généralement quand notre code bogue, il ne faut pas imputer la faute à la bibliothèque dont on se sert, mais plus à une erreur (syntaxe, logique, inattention) commise par nous-même, d'autant plus lorsqu'on est débutant et que l'on voit des bogues partout.


Avant de présenter du code, il faudrait quand même le rendre présentable, c-à-d lisible et compréhensible. Si je te présente une classe obscure contenant des méthodes avec des noms tout aussi obscurs contenant des variables également nommées avec random.shuffle, le tout sans aucun commentaire, comment veux-tu que l'on y comprenne quelque chose ?


Pour programmer, il faut avoir un minimum de rigueur.


Pourquoi as-tu besoin de cette bibliothèque customtkinter ?


Je conçois que tu désires une interface un peu plus jolie, mais avant tout il vaudrait mieux te familiariser avec cette bibliothèque graphique qu'est tkinter et en comprendre les rouages.


Ensuite il n'y a pas que tkinter comme gui si tu tiens à réaliser de jolies fenêtres, qt ou encore wx sont à la base un peu plus "travaillées", mais plus difficle à appréhender.


Sinon, tu regardes ce que donnent les exemples de code de cette bibliothèque pour t'assurer que cela fonctionne correctement.


https://github.com/TomSchimansky/CustomTkinter#example-program

https://github.com/TomSchimansky/CustomTkinter/tree/master/examples

0
pycarpe Messages postés 16 Date d'inscription lundi 24 janvier 2022 Statut Membre Dernière intervention 9 août 2022
Modifié le 8 août 2022 à 07:29

Hello, 

Tout d'abord merci d'avoir répondu aussi vite. 

Oui j'avoue mon code n'est pas explicite. Je pourrais le modifier pour le rendre plus visible mais on va faire plus simple.

Prenons le premier exemple que tu m'as envoyé https://github.com/TomSchimansky/CustomTkinter#example-program

import tkinter
import customtkinter

customtkinter.set_appearance_mode("System")  # Modes: system (default), light, dark
customtkinter.set_default_color_theme("blue")  # Themes: blue (default), dark-blue, green

app = customtkinter.CTk()  # create CTk window like you do with the Tk window
app.geometry("400x240")

def button_function():
    print("button pressed")

# Use CTkButton instead of tkinter Button
button = customtkinter.CTkButton(master=app, text="CTkButton", command=button_function)
button.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)

app.mainloop()

Là le code fait bien ce qu'on lui demande de faire pas de souci jusque là.

Et si je transforme le code comme ceci en utilisant seulement tkinter et en modifiant la ligne 14 et 15:

from tkinter import *
import customtkinter

customtkinter.set_appearance_mode("System")  # Modes: system (default), light, dark
customtkinter.set_default_color_theme("blue")  # Themes: blue (default), dark-blue, green

app = Tk()  # create CTk window like you do with the Tk window
app.geometry("400x240")

def button_function():
    print("button pressed")

# Use CTkButton instead of tkinter Button
button = Button(master=app, text="CTkButton")
button["command"] = button_function
button.place(relx=0.5, rely=0.5, anchor=CENTER)

app.mainloop()

Toujours pas de souci jusque là aussi, le code fait bien ce qu'on lui demande.

Par contre si je reprend cette dernière modification du code et que je change juste tkinter par customtkinter :

import tkinter
import customtkinter

customtkinter.set_appearance_mode("System")  # Modes: system (default), light, dark
customtkinter.set_default_color_theme("blue")  # Themes: blue (default), dark-blue, green

app = customtkinter.CTk()  # create CTk window like you do with the Tk window
app.geometry("400x240")

def button_function():
    print("button pressed")

# Use CTkButton instead of tkinter Button
button = customtkinter.CTkButton(master=app, text="CTkButton")
button["command"] = button_function
button.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)

app.mainloop()

Là il ne se passe plus rien lorsque l'on clique sur le bouton...Y-a-t-il une explication à cela?

Seul moyen de pouvoir obtenir ce que l'on veut c'est de remplacer la ligne 15 par :

button.configure(command = button_function)

Ce qui n'est pas nécessaire avec tkinter.

0

Bonjour, pour information, lorsque tu fais :
 

button["command"] = button_function


Cela utilise la méthode __setitem__, une façon de définir des valeurs d'un objet comme dans un dictionnaire. Si tu es curieux, tu jettes un oeil au code source pyhton de tkinter, tu cherches cette méthode __setitem__, et oh on tombe sur :
 

def __setitem__(self, key, value):
    self.configure({key: value})


Comme quoi cette façon est une facilité ajoutée au dev de tkinter sur python.

Mais oh, encore mieux avec ta bibliothèque, on peut directement changer la valeur de command en faisant :

button.command = button_function


Le dev de cette bibliothèque a jugé bon de faire certaines options de configuration tkinter des attributs de classes, suoer sympa non =)

N'hésite pas à consulter la doc, voir examiner le code source des bibliothèques python ;)

0
pycarpe Messages postés 16 Date d'inscription lundi 24 janvier 2022 Statut Membre Dernière intervention 9 août 2022
8 août 2022 à 13:22

Ok merci. Le fait que le dev de custom n'ait pas gardé le même principe que la méthode __setitem__,n'était pas forcément d'une logique implacable pour moi. Cela dit pas besoin d'être condescendant non plus j'ai pas 8ans. On n'a pas tous la même expérience. Sinon à quoi bon servent les forums? Bref plus de bienveillance et moins de condescendance vis à vis des débutants serait bienvenu dans ce forum.  A+++

0
mouette_ombrageuse
8 août 2022 à 21:54

Bonsoir, désolé si tu as mal interprété mes propos qui en aucun cas ne se voulaient condescendants, mon message était plus pour souligner qu'il n'y a rien de mieux que de consulter la documentation, rien de plus, cette bibliothèque tout comme toi, je ne la connaît pas.

Bonne continuation.

0