Pb checkbutton et variable associée

Résolu
Bonjour,
Je bute à nouveau sur une erreur liée à la gestion des "cases à cocher".
Attachée, une fenêtre de l'appli Terminal avec l'erreur et l'écran généré ainsi que le code.

Ma variable est bien initialisée avant utilisation. Elle est testée dans la procédure associée à l'option "commande" de l'instruction de création du bouton.
Elle est ensuite testée dans cette procédure ... et c'est la que ça se gate.
Merci de votre aide.

Claude

def autre_tirage():  
    nb_case = 0
    if (r_v_c1.get()):
        nb_case=nb_case + 1
    if (r_v_c2.get()):
        nb_case=nb_case + 1
    if (r_v_c3.get()):
        nb_case=nb_case + 1
    if (r_v_c4.get()):
        nb_case=nb_case + 1
    if (r_v_c5.get()):
        nb_case=nb_case + 1
    if nb_case != 2:
        Label(can_gen, text= "Attention ne cochez que 2 cases!     " ,bg='#FEFEE2',fg='red').place(x=40, y= 310) 
        r_v_c1 = BooleanVar(value=False)
        r_v_c2 = BooleanVar(value=False)
        r_v_c3 = BooleanVar(value=False)
        r_v_c4 = BooleanVar(value=False)
        r_v_c5 = BooleanVar(value=False)
    else:
        fois +=1
....

####### Programme principal ###################### 
# Définitions des variables globales    
choix = ['blue','green','red','yellow','purple','pink','white']
partie_en_cours = 0
palette = {}
lig_courant =['vide','vide','vide','vide','vide']
fois=0


####### Début du programme principal #############
fen1=Tk()
fen1.title("Jeu AZ V1.0")
fen1.geometry("420x470")
can_gen=Canvas(fen1, width=360, height=410, bg ="#FEFEE2")
can_gen.place(x=30,y=30)
aff_widg(can_gen)
r_v_c1 = BooleanVar(value=False)
r_v_c2 = BooleanVar(value=False)
r_v_c3 = BooleanVar(value=False)
r_v_c4 = BooleanVar(value=False)
r_v_c5 = BooleanVar(value=False)
c1 = Checkbutton(can_gen, text = "1", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c1).place(x=40,y=280)
c2 = Checkbutton(can_gen, text = "2", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c2).place(x=80,y=280)
c3 = Checkbutton(can_gen, text = "3", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c3).place(x=120,y=280)
c4 = Checkbutton(can_gen, text = "4", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c4).place(x=160,y=280)
c5 = Checkbutton(can_gen, text = "5", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c5).place(x=200,y=280)
valid = Button(can_gen, text = "Validez", height = 2, width = 7,bg ="#FEFEE2",fg='red',command = autre_tirage).place(x=295,y=280)

Button(can_gen, text='Démarrer\nune partie',bg='#FFE4C4',fg='red',command = lancement).place(x=10, y= 370)
Button(can_gen, text='FIN \nde partie',bg='#AD4F09',fg='red', command = fen1.quit).place(x=250,y=370)

####### Boucle d'attente d'évènements ##############
...




Configuration: Macintosh / Safari 14.0.1

9 réponses

  1. Désolé. Voilà l'ensemble du code.
    Merci.
    Claude

    #!/usr/bin/env python3.9
    #######################
    # #
    # Jeu AZ #
    # #
    #######################

    from tkinter import *
    import random
    import time

    ###### Définition des fonctions ##############
    def aff_widg(canva):
    for i in range(5):
    for j in range(5):
    canva.create_rectangle((40*(i+1),40*(j+1)),((40*(i+1)+40),40*(j+1)+40))

    #def maj_palette(co):
    #########
    # mettre à jour le dico par +1 sur couleur tirée

    def sel_coul():
    ind=random.randint(1,7)
    coul=choix[ind-1]
    palette[coul] +=1
    return coul

    ####Début de partie
    def lancement():
    palette.clear
    for c in range(7):
    palette[choix[c-1]] = 0
    for i in range(5):
    couleur=sel_coul()
    can_gen.create_rectangle(((40*(i+1),40),((40*(i+1)+40),40+40)), fill=couleur,width=2, outline='black')
    lig_courant[i]=couleur
    print (lig_courant)
    print (palette)
    Label(can_gen, text= "Pour chaque ligne supplémentaire\n cochez 2 cases et validez",bg='#FEFEE2',fg='blue').place(x=40, y= 310)

    def autre_tirage():
    nb_case = 0
    if (r_v_c1.get()):
    nb_case=nb_case + 1
    if (r_v_c2.get()):
    nb_case=nb_case + 1
    if (r_v_c3.get()):
    nb_case=nb_case + 1
    if (r_v_c4.get()):
    nb_case=nb_case + 1
    if (r_v_c5.get()):
    nb_case=nb_case + 1
    if nb_case != 2:
    Label(can_gen, text= "Attention ne cochez que 2 cases! " ,bg='#FEFEE2',fg='red').place(x=40, y= 310)
    r_v_c1 = BooleanVar(value=False)
    r_v_c2 = BooleanVar(value=False)
    r_v_c3 = BooleanVar(value=False)
    r_v_c4 = BooleanVar(value=False)
    r_v_c5 = BooleanVar(value=False)
    else:
    fois +=1
    if (r_v_c1.get()):
    couleur=sel_coul()
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=couleur,width=2, outline='black')
    lig_courant[i]=couleur
    else:
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=lig_courant[i],width=2, outline='black')
    if (r_v_c2.get()):
    couleur=sel_coul()
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=couleur,width=2, outline='black')
    lig_courant[i]=couleur
    else:
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=lig_courant[i],width=2, outline='black')
    if (r_v_c3.get()):
    couleur=sel_coul()
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=couleur,width=2, outline='black')
    lig_courant[i]=couleur
    else:
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=lig_courant[i],width=2, outline='black')
    if (r_v_c4.get()):
    couleur=sel_coul()
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=couleur,width=2, outline='black')
    lig_courant[i]=couleur
    else:
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=lig_courant[i],width=2, outline='black')
    if (r_v_c5.get()):
    couleur=sel_coul()
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=couleur,width=2, outline='black')
    lig_courant[i]=couleur
    else:
    can_gen.create_rectangle(((40*(fois),40),((40*(fois)+40),40+40)), fill=lig_courant[i],width=2, outline='black')

    def rien():
    return 1

    ####### Programme principal ######################
    # Définitions des variables globales
    choix = ['blue','green','red','yellow','purple','pink','white']
    partie_en_cours = 0
    palette = {}
    lig_courant =['vide','vide','vide','vide','vide']
    fois=0

    ####### Début du programme principal #############
    fen1=Tk()
    fen1.title("Jeu AZ V1.0")
    fen1.geometry("420x470")
    can_gen=Canvas(fen1, width=360, height=410, bg ="#FEFEE2")
    can_gen.place(x=30,y=30)
    aff_widg(can_gen)
    r_v_c1 = BooleanVar(value=False)
    r_v_c2 = BooleanVar(value=False)
    r_v_c3 = BooleanVar(value=False)
    r_v_c4 = BooleanVar(value=False)
    r_v_c5 = BooleanVar(value=False)
    c1 = Checkbutton(can_gen, text = "1", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c1).place(x=40,y=280)
    c2 = Checkbutton(can_gen, text = "2", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c2).place(x=80,y=280)
    c3 = Checkbutton(can_gen, text = "3", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c3).place(x=120,y=280)
    c4 = Checkbutton(can_gen, text = "4", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c4).place(x=160,y=280)
    c5 = Checkbutton(can_gen, text = "5", height = 2, width = 5,bg ="#FEFEE2",variable= r_v_c5).place(x=200,y=280)
    valid = Button(can_gen, text = "Validez", height = 2, width = 7,bg ="#FEFEE2",fg='red',command = autre_tirage).place(x=295,y=280)

    Button(can_gen, text='Démarrer\nune partie',bg='#FFE4C4',fg='red',command = lancement).place(x=10, y= 370)
    Button(can_gen, text='FIN \nde partie',bg='#AD4F09',fg='red', command = fen1.quit).place(x=250,y=370)

    ####### Boucle d'attente d'évènements ##############
    fen1.mainloop()

    ####### Effacement fenêtre - Sortie programme ######
    fen1.destroy()
    ####################################################

    0
    1. Dans ta fonction autre_tirage() tu redéfinis r_v_c1 (et les autres) et donc l'interpréteur Python,

      qui analyse tout le code avant de l'exécuter trouve que tu teste r_v_c1 avant de

      l'avoir initialisée, bien qu'elle le soit déjà avant, juste après la définition de ta fenetre

      De plus, à mon avis, la variable fois est inconnue dans cette fonction

      ainsi que la variable i :
      lig_courant[i]=couleur


      Autre chose : si tu veux afficher "Attention ne cochez que 2 cases!", il faut écrire

      if nb_case > 2: 
      et non pas
       if nb_case != 2:
      0
      1. Merci Phil_87 pour ta réponse.
        Je vais regarder mon code de plus prêt.
        L'idée dans la fonction "autre_tirage" était de remettre à 0 (réinitialiser les 5 variables) compte_tenu du fait que plus de 2 ou moins de 2 cases avaient été saisies. Dans le cas contraire (else) je traite les cas cochées.
        Par ailleurs fois et lit_courant sont des variables globales.
        Le != s'explique par le fait que je veux 2 cases cochées (pas plus et pas moins).
        Merci encore pour tes conseils.
        Claude
        0
      2. @cvan85Si tu veux exactement 2 case cochées, alors le message doit être:

        "Attention cochez exactement 2 cases!" :-)
        0
    2. Bonjour Phil_1857,

      J'ai scrupuleusement suivi les 2 méthodes proposées par le lien. Mais effectivement le résultat n'est pas celui de l'exemple fourni avec notamment les N° de lignes.
      Lors de mon précèdent post il y a quelques jours, relatif à une question du même genre, j'étais sur OSX 10.11 et la procédure a fonctionné.
      J'ai migré depuis sur un autre Mac sous BIg Sur (11.0.1). Est ce que ça explique que ça fonctionne moins bien ?
      Je pense que j'ai une certaine habitude des modes d'emploi (45 ans d'informatique mais c'est vrai novice en PYTHON et langage OO).
      Désolé .
      Claude
      0
      1. Pour le problème des balises, je ne crois pas que les créateurs du site auraient fait un truc qui

        ne fonctionne que sur certaines machines...

        Il faut copier le code dans ton message, puis le sélectionner entièrement à la souris,

        puis cliquer sur la petite flèche noire tête en bas et choisir python dans la liste

        Cela insère une balise code_python en début de code et une balise /code à la fin

        Quand tu valides ta réponse, tu voit apparaitre ton code comme dans mon exemple,

        avec les couleurs et tout...
        0
        1. Phil_1857,

          Je viens de refaire la manip, ça fonctionne.
          J'avais dû mal m'y prendre.
          Concernant la remise à False de mes variables j'ai utilisé "set" et évidemment je n'ai plus le pb de double initialisation.
          Merci.
          Claude

          if nb_case != 2:
                  Label(can_gen, text= "Attention ne cochez que 2 cases!     " ,bg='#FEFEE2',fg='red').place(x=40, y= 310) 
                  r_v_c1.set(False)
                  r_v_c2.set(False)
                  r_v_c3.set(False)
                  r_v_c4.set(False)
                  r_v_c5.set(False)
          0
          1. ok, très bien

            ca ne résout le problème de la variable i qui est inconnue dans autre_tirage mais bon ..
            0
            1. Oui c'est vrai.
              Suite à ta remarque, je l'ai remplacé par une indexation "en dur" sur les 5 cas.

              Méthode de travail un peu empirique je te l'accorde.
              Je vais m'efforcer d'être plus rigoureux. Même si maintenant je développe pour le fun.

              Encore merci.

              Claude
              0