Partage
  • Partager sur Facebook
  • Partager sur Twitter

Améliorer le déplacmeent d'objets à la souris

    1 février 2023 à 14:54:37

    Bonjour,

    Je suis toujours sur mon logiciel de numération pour l'école primaire et j'ai pas mal avancé.

    Pour information il s'agit d'un logiciel sous licence libre que je maintiens sur :

    https://forge.aeif.fr/achampollion/numeration

    où vous pouvez consulter l'intégralité du code et télécharger un exécutable Windows si nécessaire.

    Je débute depuis un mois à partir de zéro et sans aucune formation le codage en Python à partir de diverses sources documentaire du web, et vos bons conseils. Il est probable que la consultation du code vous donne matière à pleurer 😉

    Bref. J'ai bricolé une solution pour gérer des déplacements d'objets et dessiner des rectangles "select" pour sélectionner des objets.. Ça fonctionne, et même très bien sur mon PC sous Linux, mais sur Windows avec un autre PC de gamme équivalente, le rectangle "scintille" un peu et les objets subissent un scintillement blanc sur le dessus quand on les déplace vers le haut. Ce n'est qu'un problème esthétique, mais si je peux y remédier ... 😉

    Je ne sais pas si c'est lié aux perfs du processeur ou à l'OS, je n'ai pas la possibilité d'effectuer un autre test croisé pour le moment.

    Je me dis que mon algorithme est peut-être à améliorer pour consommer moins de ressources et que le problème sous Windows vient de là.

    Par exemple, comme je ne sais pas modifier les dimensions de mon rectangle "select", je le supprime et le re-crée à chaque déplacement de souris, j'ai conscience que c'est consommateur de ressources mais je ne sais pas faire autrement.

    Pareil pour le déplacement d'objet, je parcoure tous les objets du canvas pour comparer les coordonnées de la souris avec chacun d'entre eux ... il y a probablement moyen d'être plus efficient.

    Qu'en pensez-vous ?

    Le déplacement d'objets et le dessin du rectangle ;

    DETECTION_CLIC_SUR_OBJET=False
    
    def Clic(event):
        global DETECTION_CLIC_SUR_OBJET, diffx, diffy, objetbouge, select, rectx, recty
        if ok==1:
            # position du pointeur de la souris
            X = event.x
            Y = event.y
            # coordonnées du rectangle qui encadre l'objet
            for i in [*objets_unites,*objets_dizaines,*objets_centaines,*objets_milliers,*objets_dizgauche,*objets_centgauche,*objets_millgauche]:
                [x1,y1,x2,y2] = zone_princ.bbox(i)
                if x1 < X < x2 and y1 < Y < y2:
                    DETECTION_CLIC_SUR_OBJET = 1
                    objetbouge=i
                    zone_princ.tag_raise(objetbouge)
                    #calcul de la position relative du pointeur au moment du clic
                    diffx=X-x1
                    diffy=Y-y1
            if DETECTION_CLIC_SUR_OBJET==0:
                select=zone_princ.create_rectangle(X,Y,X,Y,outline="blue", width=3)
                rectx=X
                recty=Y
                DETECTION_CLIC_SUR_OBJET = 2
    
    def Drag(event):
        global select, ok
        """ Gestion de l'événement bouton gauche enfoncé """
        if DETECTION_CLIC_SUR_OBJET==1 and ok==1:
            ok=0
            X = event.x
            Y = event.y
            # mise à jour de la position de l'objet
            zone_princ.moveto(objetbouge, X-diffx,Y-diffy)
            ok=1
        elif DETECTION_CLIC_SUR_OBJET == 2 and ok==1:
            ok=0
            X = event.x
            Y = event.y
            zone_princ.delete(select)
            select=zone_princ.create_rectangle(rectx,recty,X,Y,outline="blue", width=3)
            ok=1

    Le code complet :

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from tkinter import *
    from random import *
    import tkinter.font as tkFont
    import time
    from statistics import mean
    
    #Création de la fenêtre
    
    fenetre = Tk()
    larg=fenetre.winfo_screenwidth()
    haut=fenetre.winfo_screenheight()
    fenetre.title("Numération")
    fenetre.geometry(f"{larg}x{haut}+0+0")
    fenetre.attributes("-fullscreen", 1)
    
    #Création des cadres
    
    zone_haut=Frame(fenetre, height=100, width=larg)
    zone_haut.grid(in_=fenetre, row=0,column=0, columnspan=2, sticky='nesw')
    
    zone_gauche=Frame(fenetre, width=100, height=haut)
    zone_gauche.grid(row=1,column=0, sticky='nesw')
    
    zone_princ=Canvas(fenetre, width=larg-100, height=haut-100, relief=GROOVE, borderwidth=5)
    zone_princ.grid(row=1,column=1)
    
    
    zone_gauche.columnconfigure(0,minsize=25)
    zone_gauche.columnconfigure(1,minsize=25)
    zone_gauche.columnconfigure(2,minsize=25)
    zone_gauche.columnconfigure(3,minsize=25)
    
    #Variables globales de départ
    
    tropde=[]
    
    #Dimensions du canvas
    larg_canvas=larg-100
    haut_canvas=haut-100
    #Marge extérieur des colonnes
    margey=50
    margex=10
    #Nombre représenté
    nombre=0
    milliers=centaines=dizaines=unites=0
    #Nombre de colonnes
    nbcolonnes=2
    ordre=IntVar()
    ordre.set(0)
    lignes=IntVar()
    lignes.set(1)
    couleurs=IntVar()
    couleurs.set(0)
    aff_compteur=IntVar()
    aff_compteur.set(1)
    ok=1
    l = 30
    boutons=[]
    maxu=maxd=maxc=maxm=9
    larg_unite=45
    larg_dizaine=450
    
    #Polices
    gros = tkFont.Font(family='Helvetica', size=20, weight='bold')
    tres_gros = tkFont.Font(family='Helvetica', size=30, weight='bold')
    
    #Images
    img_corbeille=PhotoImage(file="images/corbeille.png")
    img_minicorbeille = PhotoImage(file="images/minicorbeille.png")
    img_verifie=PhotoImage(file="images/verifie.png")
    img_quitter=PhotoImage(file="images/quitter.png")
    img_cadenas_ferme=PhotoImage(file="images/cadenas_ferme.png")
    img_cadenas_ouvert=PhotoImage(file="images/cadenas_ouvert.png")
    img_oeil=PhotoImage(file="images/oeil.png")
    img_oeil_inactif=PhotoImage(file="images/oeil_inactif.png")
    img_unite=PhotoImage(file="images/grandes/unite.png")
    img_dizaine=PhotoImage(file="images/grandes/dizaine_lignes_jaune.png")
    img_centaine=PhotoImage(file="images/grandes/centaine_lignes_jaune.png")
    img_millier=PhotoImage(file="images/petites/millier_lignes_jaune.png")
    
    #Bouton quitter
    
    quitter=Button(zone_haut,image=img_quitter, relief="flat", command=fenetre.destroy)
    
    #Création des zones milliers, centaines, dizaines, unités
    
    liste_4=("milliers","centaines","dizaines","unites")
    liste_3=("centaines","dizaines","unites")
    liste_2=("dizaines","unites")
    
    interu=interd=interc=interm=interg=1
    
    aff_compteur_unite = Button(zone_haut, image=img_oeil, command=lambda: affichage_compteur(aff_compteur_unite,compteur_unites,interu))
    aff_compteur_dizaine = Button(zone_haut, image=img_oeil, command=lambda: affichage_compteur(aff_compteur_dizaine,compteur_dizaines,interd))
    aff_compteur_centaine = Button(zone_haut, image=img_oeil, command=lambda: affichage_compteur(aff_compteur_centaine,compteur_centaines,interc))
    aff_compteur_millier = Button(zone_haut, image=img_oeil, command=lambda: affichage_compteur(aff_compteur_millier,compteur_milliers,interm))
    titreu=Label(zone_haut, text="U",font=gros, justify=CENTER)
    titred=Label(zone_haut, text="D",font=gros, justify=CENTER)
    titrec=Label(zone_haut, text="C",font=gros, justify=CENTER)
    titrem=Label(zone_haut, text="M",font=gros, justify=CENTER)
    
    
    
    def affichage_compteur(bouton,type_compteur,inter):
        global interu, interd, interc, interm, interg
        if inter==1:
            bouton.configure(image=img_oeil_inactif)
            type_compteur.place_forget()
            if type_compteur==compteur_unites:
                interu=0
            if type_compteur==compteur_dizaines:
                interd=0
            if type_compteur==compteur_centaines:
                interc=0
            if type_compteur==compteur_milliers:
                interm=0
            if type_compteur==compteur:
                interg=0
        else:
            bouton.configure(image=img_oeil)
            if type_compteur==compteur_unites:
                interu=1
                type_compteur.place(x=(liste_unite[0] + liste_unite[2]) / 2 + 100, y=80, anchor=W)
            if type_compteur==compteur_dizaines:
                interd=1
                type_compteur.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2 + 100, y=80, anchor=W)
            if type_compteur==compteur_centaines:
                interc=1
                type_compteur.place(x=(liste_centaine[0] + liste_centaine[2]) / 2 + 100, y=80, anchor=W)
            if type_compteur==compteur_milliers:
                type_compteur.place(x=(liste_millier[0] + liste_millier[2]) / 2 + 100, y=80, anchor=W)
                interm=1
            if type_compteur==compteur:
                interg=1
                compteur.place(x=5, y=50, anchor=W, width=200, height=80)
    
    lock=0
    
    def verr(self):
        global lock
        if lock==0:
            lock=1
            choix_verr.config(image=img_cadenas_ferme)
            for i in (boutons):
                i.configure(state=DISABLED)
        else:
            lock=0
            choix_verr.config(image=img_cadenas_ouvert)
            for i in (boutons):
                i.configure(state=ACTIVE)
    
    choix_verr=Button(zone_gauche, image=img_cadenas_ouvert, command=lambda: verr("self"))
    
    #Création des colonnes
    def rectangles(mode):
        global larg_colonne, haut_canvas
        posx = margex
        posy = margey
        for i in (mode):
            zone_princ.create_rectangle(posx,posy,larg_colonne+posx,haut_canvas-margey, fill="#fff", width=0,tags=f"{i}")
            zone_princ.create_rectangle(posx+larg_colonne-5, posy, larg_colonne + posx, haut_canvas - margey, fill="#878787", width=0, tags="deco")
            #zone_princ.create_rectangle(posx, haut_canvas - margey - 5, larg_colonne + posx, haut_canvas - margey, fill="#f6f6f6", width=0, tags="deco")
            zone_princ.create_polygon(posx, haut_canvas-margey-5,posx+larg_colonne-5,haut_canvas-margey-5,posx+larg_colonne,haut_canvas-margey,posx,haut_canvas-margey, fill="#f6f6f6", width=0, tags="deco")
    
            posx=posx+margex+larg_colonne
    
    def change_images():
        global larg_unite,larg_dizaine
        if couleurs.get()==0:
            couleur="jaune"
        else:
            couleur="multi"
        if int(nbcolonnes)==2:
            if larg_colonne<460 or haut_colonne<800:
                taille="moyennes"
                larg_unite=22.5
                larg_dizaine=225
            else:
                taille="grandes"
                larg_unite=45
                larg_dizaine=450
        elif int(nbcolonnes)==3:
            if larg_colonne<460:
                taille="petites"
                larg_unite=14
                larg_dizaine=140
            else:
                taille="moyennes"
                larg_unite=22.5
                larg_dizaine=225
        else:
            taille="petites"
            larg_unite=14
            larg_dizaine=140
        if lignes.get()==0:
            type="muet"
        else:
            type="lignes"
        img_unite.configure(file=f"images/{taille}/unite.png")
        img_dizaine.configure(file=f"images/{taille}/dizaine_{type}_{couleur}.png")
        img_centaine.configure(file=f"images/{taille}/centaine_{type}_{couleur}.png")
        img_millier.configure(file=f"images/{taille}/millier_{type}_{couleur}.png")
        zone_princ.update()
    
    
    #Initialisation des éléments
    def init():
        global nb, larg_colonne, liste_millier, liste_centaine, liste_dizaine, liste_unite, haut_colonne, nombrexu, nombreyu, nombrezu, nombrexd, nombreyd, nombrezd, nombrexc, nombreyc, nombrezc, nombrexm, nombreym, nombrezm, centreu, centred, centrec, centrem
        nb=int(nbcolonnes)
        compteur.place(x=5, y=50, anchor=W, width=200, height=80)
        quitter.place(x=larg, y=0, anchor=NE)
        boutons.append(quitter)
        compteur.configure(background="#bdffd5")
        haut_colonne = haut-100-2*margey
        if nb==4:
            larg_colonne = (larg_canvas - (5 * margex)) / 4
            rectangles(liste_4)
        if nb==3:
            larg_colonne = (larg_canvas - (4 * margex)) / 3
            rectangles(liste_3)
        if nb==2:
            larg_colonne = (larg_canvas - (3 * margex)) / 2
            rectangles(liste_2)
        change_images()
        nombrexu = 5
        nombreyu = (haut_colonne // (larg_colonne/6))
        nombrezu = nombrexu * nombreyu
        nombrexd = 2
        nombreyd = int((haut_colonne / (larg_colonne/12)))
        nombrezd = nombrexd*nombreyd
        nombrexc = int((larg_colonne / 160))
        nombreyc = int((haut_colonne / 160))
        nombrezc = nombrexc * nombreyc
        nombrexm = int((larg_colonne / 175))
        nombreym = int((haut_colonne / 90))
        nombrezm = (nombrexm * nombreym)-nombrexm
        if nb==4:
            liste_millier = zone_princ.coords("milliers")
            liste_centaine = zone_princ.coords("centaines")
            range_milliers = Button(zone_princ, text="Ranger", command=lambda: action_range("millier"))
            casse_millier = Button(zone_princ, text="Casser >>>", command=lambda: casse("millier", milliers))
            suppr_millier = Button(zone_princ, text="-", command=lambda: man_suppr("millier"))
            add_millier = Button(zone_princ, text="+",command=lambda: new("millier", 1000, "normal"))
            reset_millier = Button(zone_haut, image=img_minicorbeille, command=lambda: reset("millier"))
            reset_millier.place(x=(liste_millier[0] + liste_millier[2]) / 2 + 80, y=35, anchor=E)
            aff_compteur_millier.place(x=(liste_millier[0] + liste_millier[2]) / 2 + 120, y=35, anchor=W)
            compteur_milliers.place(x = (liste_millier[0]+liste_millier[2])/2+100, y = 80, anchor=CENTER)
            casse_millier.place(x=(liste_millier[0]+liste_millier[2])/2,y=haut_canvas-margey/2, anchor=CENTER)
            range_milliers.place(x=((liste_millier[0]+liste_millier[2])/2)+l,y=margey/2, anchor=W, width=2*l)
            add_millier.place(x=(liste_millier[0]+liste_millier[2])/2,y=margey/2, anchor=W, width=l)
            suppr_millier.place(x=(liste_millier[0]+liste_millier[2])/2,y=margey/2, anchor=E, width=l)
            groupe_centaines = Button(zone_princ, text="<<<", command=lambda: gauche("millier", centaines))
            groupe_centaines.place(x=(liste_centaine[0] + liste_centaine[2]) / 2, y=haut_canvas - margey / 2, anchor=E)
            titrem.place(x=(liste_millier[0] + liste_millier[2]) / 2 + 100, y=40, anchor=CENTER)
            boutons.extend([add_millier,suppr_millier,reset_millier])
            centrem=(liste_millier[0]+larg_colonne/2,liste_millier[1]+haut_colonne/2)
        if nb>=3:
            liste_centaine = zone_princ.coords("centaines")
            liste_dizaine = zone_princ.coords("dizaines")
            range_centaines = Button(zone_princ, text="Ranger", command=lambda: action_range("centaine"))
            reset_centaine = Button(zone_haut, image=img_minicorbeille, command=lambda: reset("centaine"))
            casse_centaine = Button(zone_princ, text="Casser >>>", command=lambda: casse("centaine", centaines))
            select_centaine = Button(zone_princ, text="Grouper", command=lambda: groupe("centaine","bouton"))
            add_centaine = Button(zone_princ, text="+", command=lambda: new("centaine", 100, "normal"))
            suppr_centaine = Button(zone_princ, text="-", command=lambda: man_suppr("centaine"))
            compteur_centaines.place(x=(liste_centaine[0] + liste_centaine[2]) / 2 + 100, y=80, anchor=CENTER)
            suppr_centaine.place(x=((liste_centaine[0] + liste_centaine[2]) / 2) - l, y=margey / 2, anchor=E, width=l)
            degroupe_centaine = Button(zone_princ, text="Dégrouper", command=lambda: degroupe("centaine","bouton"))
            degroupe_centaine.place(x=((liste_centaine[0] + liste_centaine[2]) / 2) - 2*l, y=margey / 2,anchor=E)
            add_centaine.place(x=(liste_centaine[0] + liste_centaine[2]) / 2, y=margey / 2, anchor=E, width=l)
            range_centaines.place(x=((liste_centaine[0] + liste_centaine[2]) / 2) + 2*l, y=margey / 2, anchor=W, width=2*l)
            casse_centaine.place(x=(liste_centaine[0] + liste_centaine[2]) / 2, y=haut_canvas - margey / 2, anchor=W)
            select_centaine.place(x=(liste_centaine[0] + liste_centaine[2]) / 2, y=margey / 2, anchor=W, width=2*l)
            reset_centaine.place(x=(liste_centaine[0] + liste_centaine[2]) / 2 + 80, y=35, anchor=E)
            aff_compteur_centaine.place(x=(liste_centaine[0] + liste_centaine[2]) / 2 + 120, y=35, anchor=W)
            groupe_dizaines = Button(zone_princ, text="<<<", command=lambda: gauche("centaine", dizaines))
            groupe_dizaines.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2, y=haut_canvas - margey / 2, anchor=E)
            titrec.place(x=(liste_centaine[0] + liste_centaine[2]) / 2 + 100, y=40, anchor=CENTER)
            boutons.extend([add_centaine,suppr_centaine,reset_centaine,])
            centrec = [liste_centaine[0] + larg_colonne/2, liste_centaine[1] + haut_colonne / 2]
    
        #Dans tous les cas création des boutons dieaines et unités
        #Les positions
        liste_dizaine = zone_princ.coords("dizaines")
        liste_unite = zone_princ.coords("unites")
        #Les boutons et les compteurs
        range_dizaines = Button(zone_princ, text="Ranger", command=lambda: action_range("dizaine"))
        range_unites = Button(zone_princ, text="Ranger", command=lambda: action_range("unite"))
        casse_dizaine = Button(zone_princ, text="Casser >>>", command=lambda: casse("dizaine", dizaines))
        reset_unite = Button(zone_haut, image=img_minicorbeille, command=lambda: reset("unite"))
        groupe_unites = Button(zone_princ,text="<<<", command=lambda: gauche("dizaine", unites))
        select_unite = Button(zone_princ, text="Grouper", command=lambda: groupe("unite","bouton"))
        select_dizaine = Button(zone_princ, text="Grouper", command=lambda: groupe("dizaine","bouton"))
        suppr_unite = Button(zone_princ, text="-", command=lambda: man_suppr("unite"))
        suppr_dizaine = Button(zone_princ, text="-", command=lambda: man_suppr("dizaine"))
        reset_dizaine = Button(zone_haut, image=img_minicorbeille, command=lambda: reset("dizaine"))
        add_unite = Button(zone_princ, text="+", command=lambda: new("unite",  1, "normal"))
        add_dizaine = Button(zone_princ, text="+", command=lambda: new("dizaine", 10, "normal"))
        select_unite.place(x=(liste_unite[0] + liste_unite[2]) / 2, y=margey / 2, anchor=W, width=2*l)
        select_dizaine.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2, y=margey / 2, anchor=W, width=2*l)
        range_unites.place(x=((liste_unite[0] + liste_unite[2]) / 2) + 2*l, y=margey / 2, anchor=W, width=2*l)
        range_dizaines.place(x=((liste_dizaine[0] + liste_dizaine[2]) / 2) + 2*l, y=margey / 2, anchor=W, width=2*l)
        add_unite.place(x=(liste_unite[0] + liste_unite[2]) / 2, y=margey / 2, anchor=E, width=l)
        add_dizaine.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2, y=margey / 2, anchor=E, width=l)
        suppr_unite.place(x=((liste_unite[0] + liste_unite[2]) / 2) - l, y=margey / 2, anchor=E, width=l)
        suppr_dizaine.place(x=((liste_dizaine[0] + liste_dizaine[2]) / 2) - l, y=margey / 2, anchor=E, width=l)
        casse_dizaine.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2, y=haut_canvas - margey / 2, anchor=W)
        groupe_unites.place(x=(liste_unite[0] + liste_unite[2]) / 2, y=haut_canvas - margey / 2, anchor=CENTER)
        reset_dizaine.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2 + 80, y=35, anchor=E)
        reset_unite.place(x=(liste_unite[0] + liste_unite[2]) / 2 + 80, y=35, anchor=E)
        aff_compteur_unite.place(x=(liste_unite[0] + liste_unite[2]) / 2 + 120, y=35, anchor=W)
        aff_compteur_dizaine.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2 + 120, y=35, anchor=W)
        compteur_dizaines.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2 + 100, y=80, anchor=CENTER)
        compteur_unites.place(x=(liste_unite[0] + liste_unite[2]) / 2 + 100, y=80, anchor=CENTER)
        titred.place(x=(liste_dizaine[0] + liste_dizaine[2]) / 2 + 100, y=40, anchor=CENTER)
        titreu.place(x=(liste_unite[0] + liste_unite[2]) / 2 + 100, y=40, anchor=CENTER)
        degroupe_dizaine = Button(zone_princ, text="Dégrouper", command=lambda: degroupe("dizaine","bouton"))
        degroupe_dizaine.place(x=((liste_dizaine[0] + liste_dizaine[2]) / 2) - 2 * l, y=margey / 2, anchor=E)
        degroupe_unite = Button(zone_princ, text="Dégrouper", command=lambda: degroupe("unite","bouton"))
        degroupe_unite.place(x=((liste_unite[0] + liste_unite[2]) / 2) - 2 * l, y=margey / 2, anchor=E)
        boutons.extend([add_unite,add_dizaine,suppr_unite,suppr_dizaine,reset_unite,reset_dizaine])
        centreu = (liste_unite[0] + larg_colonne/2, liste_unite[1] + haut_colonne / 2)
        centred = (liste_dizaine[0] + larg_colonne/2, liste_dizaine[1] + haut_colonne / 2)
    
    #Action du bouton corbeille
    def nouveau(nb):
        global nbcolonnes,larg_unite,larg_dizaine
        nbcolonnes=int(nb)
        zone_princ.delete('all')
        for widget in zone_princ.winfo_children():
            widget.place_forget()
        for widget in zone_haut.winfo_children():
            widget.place_forget()
        change_images()
        init()
        reset("tout")
    
    #Fenêtre à propos
    def apropos():
        global lock
        lock=1
        fen_apropos = Toplevel(fenetre, background='#fff', padx=100, pady=100)
        fen_apropos.geometry(f"{larg}x{haut}+0+0")
        fen_apropos.attributes("-fullscreen", 1)
        fen_apropos.title('À propos')
        texte_apropos = Label(fen_apropos, justify='left', background='#fff', text="Numération est un logiciel qui permet de représenter les milliers, centaines, dizaines et unités sous fomes de blocs de base, et d'effectuer des conversions entre colonnes.\n\nIl est écrit par Arnaud Champollion et partagé sous licence GNU/GPL.")
        texte_apropos.grid(row=0,column=0,sticky='nesw')
        def fermeture():
            global lock
            lock = 0
            fen_apropos.destroy()
        quitter = Button(fen_apropos, image=img_quitter, relief="flat", command=fermeture)
        quitter.grid(row=0,column=1)
        fen_apropos.mainloop()
    
    def aide():
        fen_aide = Toplevel(fenetre, padx=100, pady=100)
        fen_aide.geometry(f"{larg}x{haut}+0+0")
        fen_aide.title('Aide')
        fen_aide.attributes("-fullscreen", 1)
        global lock
        lock=1
        def fermeture():
            global lock
            lock = 0
            fen_aide.destroy()
        quitter = Button(fen_aide, image=img_quitter, relief="flat", command=fermeture)
        quitter.pack()
        barre=Scrollbar(fen_aide)
        texte_manuel=Text(fen_aide, height=300, width=600, background='#fff')
        barre.pack(side=RIGHT, fill=Y)
        texte_manuel.pack(side=LEFT, fill=Y)
        barre.config(command=texte_manuel.yview)
        texte_manuel.config(yscrollcommand=barre.set, wrap=WORD,tabs=('2c', '4.5c', 'right', '9c', 'center', '13c', 'numeric'), padx=20, pady=4)
        quote = """Pour ajouter un millier, une centaine, une dizaine, une unité, cliquer sur le bouton + de la colonne correspondante, ou bien utiliser la molette de la souris en se plaçant dans la colonne souhaitée. Il est également possible d'utiliser les raccourcis clavier : "m,c,d,u".
    
    Pour grouper des unités, dizaines ou centaines, cliquer sur le bouton "grouper" situé en haut de la colonne.
    Pour déplacer un groupe vers la colonne de gauche, utiliser le bouton <<< situé en bas.
    
    Pour casser un millier, une centaine ou une dizaine, cliquer sur le bouton >>> en bas de la colonne correspondante.
    
    Pour masquer un compteur particulier ou le compteur général, cliquer sur le bouton en forme d'oeil.
    
    Pour remettre à zéro une colonne ou l'ensemble, utiliser les boutons corbeille.
    
    Pour verrouiller la somme, cliquer sur le bouton "cadenas" à gauche. Cela a pour effet d'empêcher toute création ou suppression ayant pour effet de modifier le nombre total. Les remises à zéro (corbeille), modifications du nombre de colonnes, tirage aléatoire et bouton "quitter" sont également désactivés.
    
    Le bouton "Au hasard" affiche un nombre aléatoire de millliers, centaines, dizaines, unités (selon le nombre de colonnes actives). Les curseurs permettent de définir un nombre maximum pour chacune.
    
        
    Raccourcis clavier :
        
    u : ajouter une unité
    d : ajouter une dizaine
    c: ajouter une centaine
    m : ajouter un millier
    Ctrl u : supprimer une unité
    Ctrl d : supprimer une dizaine
    Ctrl c: supprimer une centaine
    Ctrl m : supprimer un millier
    
    Barre espace : supprimer tout
    
    v : voir / cacher le compteur principal
    r : ranger tous les blocs
    t : tirer un nombre au hasard (cache les compteurs)
    b : verouiller (bloquer) / déverouiller le nombre (empêche d'ajouter ou de supprimer des blocs, désactive les boutons corbeille, hasard et colonnes)
    
    Échap : quitter
    """
        texte_manuel.insert(END, quote)
        texte_manuel.config(state=DISABLED)
        fen_aide.mainloop()
    
    
    def update(self):
        val_m.configure(text=max_m.get())
        val_c.configure(text=max_c.get())
        val_d.configure(text=max_d.get())
        val_u.configure(text=max_u.get())
    
    
    
    #Bouton du choix du nombre de colonnes
    
    choixcol=Scale(zone_gauche, orient='horizontal', showvalue=0, from_=4, to=2, resolution=1, tickinterval=1, length=100, label='Colonnes', command=nouveau)
    choixcol.grid(row=2,column=0, sticky='nesw', pady=4, columnspan=4)
    boutons.append(choixcol)
    
    
    
    
    titre_m=Label(zone_gauche,text="m")
    titre_c=Label(zone_gauche,text="c")
    titre_d=Label(zone_gauche,text="d")
    titre_u=Label(zone_gauche,text="u")
    titre_m.grid(row=7,column=0,sticky='nesw')
    titre_c.grid(row=7,column=1,sticky='nesw')
    titre_d.grid(row=7,column=2,sticky='nesw')
    titre_u.grid(row=7,column=3,sticky='nesw')
    max_m=Scale(zone_gauche, orient='vertical', showvalue=0, from_=50, to=0, resolution=1, tickinterval=0, length=100, width=15, bd=0, command=update)
    max_m.grid(row=8,column=0,pady=0, padx=0)
    max_c=Scale(zone_gauche, orient='vertical', showvalue=0, from_=50, to=0, resolution=1, tickinterval=0, length=100, width=15, bd=0, command=update)
    max_c.grid(row=8,column=1, pady=0, padx=0)
    max_d=Scale(zone_gauche, orient='vertical', showvalue=0, from_=50, to=0, resolution=1, tickinterval=0, length=100, width=15, bd=0, command=update)
    max_d.grid(row=8,column=2, pady=0, padx=0)
    max_u=Scale(zone_gauche, orient='vertical', showvalue=0, from_=50, to=0, resolution=1, tickinterval=0, length=100, width=15, bd=0, command=update)
    max_u.grid(row=8,column=3, pady=0, padx=0)
    
    max_u.set(9)
    max_d.set(9)
    max_c.set(9)
    max_m.set(9)
    
    val_m=Label(zone_gauche,text=max_m.get())
    val_c=Label(zone_gauche,text=max_c.get())
    val_d=Label(zone_gauche,text=max_d.get())
    val_u=Label(zone_gauche,text=max_u.get())
    
    val_m.grid(row=9,column=0,sticky='nesw')
    val_c.grid(row=9,column=1,sticky='nesw')
    val_d.grid(row=9,column=2,sticky='nesw')
    val_u.grid(row=9,column=3,sticky='nesw')
    
    
    #Bouton à propos
    
    bouton_apropos=Button(zone_gauche, text="À propos", command=apropos)
    bouton_apropos.grid(row=14, column=0,pady=4, columnspan=4)
    bouton_aide=Button(zone_gauche, text="Aide", command=aide)
    bouton_aide.grid(row=13, column=0,pady=4, columnspan=4)
    
    #Compteur général
    
    compteur=Label(zone_haut, text=nombre, font=tres_gros, fg="#f97000",relief=GROOVE, borderwidth=5)
    compteur.place(x=5, y=50, anchor=W)
    #Compteurs
    compteur_milliers = Label(zone_haut, text=milliers, font=gros, fg="blue")
    compteur_centaines = Label(zone_haut, text=centaines, font=gros, fg="blue")
    compteur_dizaines = Label(zone_haut, text=dizaines, font=gros, fg="blue")
    compteur_unites = Label(zone_haut, text=unites, font=gros, fg="blue")
    
    
    corbeille=Button(zone_gauche, image=img_minicorbeille, command=lambda : reset("tout"))
    corbeille.grid(row=1,column=0,pady=4, columnspan=2)
    boutons.append(corbeille)
    bouton_ranger=Button(zone_gauche, text="Ranger\ntout", command=lambda : action_range("tout"))
    bouton_ranger.grid(row=4,column=0,pady=4, columnspan=4)
    
    choix_compteur=Button(zone_gauche, image=img_oeil, command=lambda: affichage_compteur(choix_compteur,compteur,interg))
    
    bouton_hasard=Button(zone_gauche, text="Mélanger", command=lambda : action_hasard("tout"))
    bouton_hasard.grid(row=5,column=0,columnspan=4)
    
    choix_compteur.grid(row=0,column=0,columnspan=2)
    choix_verr.grid(row=0,column=2,columnspan=2)
    
    #Listes des coordonnées des coins des rectangles
    
    objets_milliers=[]
    objets_centaines=[]
    objets_dizaines=[]
    objets_unites=[]
    objets_dizgauche=[]
    objets_centgauche=[]
    objets_millgauche=[]
    
    #Lancement du début
    init()
    
    
    def man_suppr(objet):
        if lock==0:
            suppr(objet)
    
    def new(objet,valeur,mode):
        if lock==0:
            if objet=="unite" or objet=="dizaine" or (objet=="centaine" and int(nbcolonnes)>2) or (objet=="millier" and int(nbcolonnes)>3):
                cree(objet, valeur, mode)
    
    def coordshasard(objet):
        if objet == "unite":
            liste_coords = liste_unite
            x1 = int(liste_coords[0] + larg_unite)
            x2 = int(liste_coords[2] - larg_unite)
            y1 = int(liste_coords[1] + larg_unite)
            y2 = int(liste_coords[3] - larg_unite)
        if objet == "dizaine":
            liste_coords=liste_dizaine
            x1 = int(liste_coords[0] + larg_dizaine / 2 + larg_unite)
            x2 = int(liste_coords[2] - larg_dizaine / 2 - larg_unite)
            y1 = int(liste_coords[1] + larg_unite)
            y2 = int(liste_coords[3] - larg_unite)
        if objet == "centaine":
            liste_coords = liste_centaine
            x1 = int(liste_coords[0] + larg_dizaine / 2 + larg_unite)
            x2 = int(liste_coords[2] - larg_dizaine / 2 - larg_unite)
            y1 = int(liste_coords[1] + larg_dizaine / 2 + larg_unite)
            y2 = int(liste_coords[3] - larg_dizaine / 2 - larg_unite)
        if objet == "millier":
            liste_coords = liste_millier
            x1 = int(liste_coords[0] + larg_dizaine / 2 + 3*larg_unite)
            x2 = int(liste_coords[2] - larg_dizaine / 2 - 3*larg_unite)
            y1 = int(liste_coords[1] + larg_dizaine / 2 + 3*larg_unite)
            y2 = int(liste_coords[3] - larg_dizaine / 2 - 3*larg_unite)
        return x1,x2,y1,y2
    
    #Boucle de création d'une image
    def cree(objet,valeur,mode):
        global nombre, milliers, centaines, dizaines, unites,x1,x2,y1,y2,coords_bouge
        #On incrémente les compteurs
        nombre=nombre+valeur
        #On récupère les coordonnées de la colonne correspondante et on incrémente le nombre de chaque
        if not mode=="groupe" and not mode=="degroupe":
            if objet=="millier":
                milliers=milliers+1
                img=img_millier
            if objet=="centaine":
                centaines=centaines+1
                img=img_centaine
            if objet=="dizaine":
                dizaines=dizaines+1
                img=img_dizaine
            if objet=="unite":
                unites=unites+1
                img=img_unite
            x1,x2,y1,y2=coordshasard(objet)
            xobjet = randint(x1, x2)
            yobjet = randint(y1, y2)
        maj()
        if objet=="millier":
            img = img_millier
            if mode == "groupe":
                objets_millgauche.append(zone_princ.create_image(coords_groupe[0]-0.5*larg_unite,coords_groupe[1]+0.5*larg_unite, image=img, tags="millgauche"))
            else:
                if ordre.get() == 0:
                    objets_milliers.append(zone_princ.create_image(xobjet, yobjet, image=img,tags=objet))
                else:
                    cible = rangement(objet, milliers - 1)
                    objets_milliers.append(zone_princ.create_image(cible, image=img,tags=objet))
        if objet=="centaine":
            img = img_centaine
            c=centaines-10*mg
            if mode=="groupe":
                objets_centgauche.append(zone_princ.create_image(coords_groupe[0],coords_groupe[1], image=img, tags="centgauche"))
            elif mode=="bouge" or mode=="degroupe":
                    objets_centaines.append(zone_princ.create_image(coords_bouge[0]-((rang_casse-5)*larg_unite),coords_bouge[1]+((rang_casse-5)*larg_unite), image=img, tags=objet))
            else:
                if ordre.get() == 1:
                    cible = rangement(objet, c - 1)
                    objets_centaines.append(zone_princ.create_image(cible, image=img, tags=objet))
                else:
                    objets_centaines.append(zone_princ.create_image(xobjet, yobjet, image=img,tags=objet))
        if objet=="dizaine":
            img = img_dizaine
            d=dizaines-10*cg
            if mode=="groupe":
                objets_dizgauche.append(zone_princ.create_image(coords_groupe[0]+larg_dizaine/2-larg_unite/2,coords_groupe[1], image=img, tags="dizgauche"))
            elif mode=="bouge" or mode=="degroupe":
                objets_dizaines.append(zone_princ.create_image(coords_bouge[0],coords_bouge[1]+larg_unite+larg_unite*1.5*(rang_casse-5), image=img, tags=objet))
            else:
                if ordre.get() == 0:
                    objets_dizaines.append(zone_princ.create_image(xobjet, yobjet, image=img, tags=objet))
                else:
                    cible = rangement(objet, d - 1)
                    objets_dizaines.append(zone_princ.create_image(cible, image=img, tags=objet))
        if objet=="unite":
            img = img_unite
            u=unites-10*dg
            if mode=="bouge" or mode=="degroupe":
                objets_unites.append(zone_princ.create_image(coords_bouge[0]+larg_unite*(rang_casse-5.5),coords_bouge[1], image=img, tags=objet))
            else:
                if ordre.get()==0:
                    objets_unites.append(zone_princ.create_image(xobjet,yobjet, image=img, tags=objet))
                else:
                    cible=rangement(objet,u-1)
                    objets_unites.append(zone_princ.create_image(cible, image=img,tags=objet))
    
    
    def rangement(objet,position):
        if objet == "unite":
            nombremax=2*nombrezu
        if objet == "dizaine":
            nombrexd = (larg_colonne - 4 * larg_unite) // larg_dizaine
            nombreyd = (haut_colonne - larg_unite) // (2*larg_unite)
            nombrezd = nombrexd * nombreyd
            if int(nbcolonnes)==2:
                nombreyd=10
            else:
                nombreyd=2
            nombremax=2*nombrezd
        if objet == "centaine":
            nombrexc=(larg_colonne - 4 * larg_unite) // larg_dizaine
            nombreyc=(haut_colonne - 4 * larg_unite) // larg_dizaine
            nombrezc=nombrexc*nombreyc
            nombremax=2*nombrezc
        if objet == "millier":
            nombrexm=(larg_colonne - 4 * larg_unite) // larg_dizaine
            nombreym=(haut_colonne - 4 * larg_unite) // 100
            nombrezm=nombrexm*nombreym
            nombremax=2*nombrezm-nombrexm
        if position < nombremax:
            if objet=="unite":
                return [(larg_colonne/6)+liste_unite[0] + (position - nombrexu * (int(position / nombrexu))) * (larg_colonne/6)+(int(position/nombrezu))*(larg_colonne/12),larg_unite*2 + liste_unite[1] + ((int(position/nombrexu))-nombreyu*(int(position/nombrezu)))*(larg_colonne/6) + (larg_colonne/12)*int(position / nombrezu)]
            if objet == "dizaine":
                if int(nbcolonnes)==2:
                    return [((liste_dizaine[0])+(liste_dizaine[2]))/2-((position//nombreyd)*(larg_unite/3)),liste_dizaine[1] + (haut_colonne/11) + (position-(nombreyd*int(position/nombreyd)))*(haut_colonne/11)+((position//nombreyd)*(larg_unite/3))]
                else:
                    return [liste_dizaine[0]+larg_dizaine/2+2*larg_unite+(larg_dizaine+2*larg_unite)*(position%nombrexd)-(position//nombrezd)*(larg_unite/3),liste_dizaine[1]+(2*larg_unite)+(2*larg_unite)*((position-((position//nombrezd)*nombrezd))//nombrexd)+(position//nombrezd)*(larg_unite/3)]
            if objet == "centaine":
                return [larg_dizaine/2+2*larg_unite + liste_centaine[0] + (position - nombrexc * (int(position / nombrexc))) * (larg_dizaine+2*larg_unite)+(int(position/nombrezc))*40,(larg_dizaine/2+larg_unite) + liste_centaine[1] + ((int(position/nombrexc))-nombreyc*(int(position/nombrezc)))*(larg_dizaine+larg_unite) + 80*int(position / nombrezc)]
            if objet == "millier":
                return [larg_dizaine*0.75+ liste_millier[0] + (position - nombrexm * (int(position / nombrexm))) * 160+(int(position/nombrezm))*20,120 + liste_millier[1] + ((int(position/nombrexm))-nombreym*(int(position/nombrezm)))*80 + 90*int(position / nombrezm)]
        else:
            if objet=="unite":
                aleau=Label(zone_princ,text="Rangement impossible\nPlacement aléatoire")
                aleau.place(x=liste_unite[0]+larg_colonne/2,y=liste_unite[1]+haut_colonne/2,anchor=CENTER, width=150)
                zone_princ.after(1000,lambda:aleau.place_forget())
            if objet=="dizaine":
                alead=Label(zone_princ,text="Rangement impossible\nPlacement aléatoire")
                alead.place(x=liste_dizaine[0]+larg_colonne/2,y=liste_dizaine[1]+haut_colonne/2,anchor=CENTER, width=200)
                zone_princ.after(1000,lambda:alead.place_forget())
            if objet=="centaine":
                aleac=Label(zone_princ,text="Rangement impossible\nPlacement aléatoire")
                aleac.place(x=liste_centaine[0]+larg_colonne/2,y=liste_centaine[1]+haut_colonne/2,anchor=CENTER, width=200)
                zone_princ.after(1000,lambda:aleac.place_forget())
            if objet=="millier":
                aleam=Label(zone_princ,text="Rangement impossible\nPlacement aléatoire")
                aleam.place(x=liste_millier[0]+larg_colonne/2,y=liste_millier[1]+haut_colonne/2,anchor=CENTER, width=200)
                zone_princ.after(1000,lambda:aleam.place_forget())
            x1, x2, y1, y2 = coordshasard(objet)
            return (randint(x1, x2), randint(y1, y2))
    
    def action_range(objet):
        global ok
        if ok==1:
            rangu = rangd = rangc = rangm = 0
            ok=0
            if objet=="unite" or objet=="tout":
                trajectoirex = []
                trajectoirey = []
                for i in (objets_unites):
                    cible=rangement("unite",rangu)
                    trajectoirex.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoirey.append(cible[1]-(zone_princ.coords(i)[1]))
                    rangu = rangu + 1
                if unites>=50:
                    rang=0
                    for j in (objets_unites):
                        zone_princ.move(j,trajectoirex[rang],trajectoirey[rang])
                        rang=rang+1
                if unites<50:
                    for j in range (30):
                        rang=0
                        for k in (objets_unites):
                            zone_princ.move(k,trajectoirex[rang]/30,trajectoirey[rang]/30)
                            rang=rang+1
                            zone_princ.update()
            if objet=="dizaine" or objet=="tout":
                for i in (objets_dizaines):
                    cible=rangement("dizaine",rangd)
                    zone_princ.move(i,cible[0]-(zone_princ.coords(i)[0]),cible[1]-(zone_princ.coords(i)[1]))
                    rangd=rangd+1
            if objet=="centaine" or objet=="tout":
                for i in (objets_centaines):
                    cible=rangement("centaine",rangc)
                    zone_princ.move(i,cible[0]-(zone_princ.coords(i)[0]),cible[1]-(zone_princ.coords(i)[1]))
                    rangc=rangc+1
            if objet=="millier" or objet=="tout":
                for i in (objets_milliers):
                    cible=rangement("millier",rangm)
                    zone_princ.move(i,cible[0]-(zone_princ.coords(i)[0]),cible[1]-(zone_princ.coords(i)[1]))
                    rangm=rangm+1
            ok=1
    def action_hasard(objet):
        global ok
        if ok==1:
            ok=0
            if objet=="unite" or objet=="tout":
                x1, x2, y1, y2 = coordshasard("unite")
                trajectoirexu = []
                trajectoireyu = []
                for i in (objets_unites):
                    xobjet = randint(x1, x2)
                    yobjet = randint(y1, y2)
                    cible=xobjet,yobjet
                    trajectoirexu.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoireyu.append(cible[1]-(zone_princ.coords(i)[1]))
                if unites>=50:
                    rang=0
                    for j in (objets_unites):
                        zone_princ.move(j,trajectoirexu[rang],trajectoireyu[rang])
                        rang=rang+1
                if unites<50:
                    for j in range (30):
                        rang=0
                        for k in (objets_unites):
                            zone_princ.move(k,trajectoirexu[rang]/30,trajectoireyu[rang]/30)
                            rang=rang+1
                            zone_princ.update()
            if objet=="dizaine" or objet=="tout":
                x1, x2, y1, y2 = coordshasard("dizaine")
                trajectoirexd = []
                trajectoireyd = []
                for i in (objets_dizaines):
                    xobjet = randint(x1, x2)
                    yobjet = randint(y1, y2)
                    cible=xobjet,yobjet
                    trajectoirexd.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoireyd.append(cible[1]-(zone_princ.coords(i)[1]))
                if dizaines>=50:
                    rang=0
                    for j in (objets_dizaines):
                        zone_princ.move(j,trajectoirexd[rang],trajectoireyd[rang])
                        rang=rang+1
                if dizaines<50:
                    for j in range (30):
                        rang=0
                        for k in (objets_dizaines):
                            zone_princ.move(k,trajectoirexd[rang]/30,trajectoireyd[rang]/30)
                            rang=rang+1
                            zone_princ.update()
            if objet=="centaine" or (objet=="tout"and int(nbcolonnes)>2):
                x1, x2, y1, y2 = coordshasard("centaine")
                trajectoirexc = []
                trajectoireyc = []
                for i in (objets_centaines):
                    xobjet = randint(x1, x2)
                    yobjet = randint(y1, y2)
                    cible=xobjet,yobjet
                    trajectoirexc.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoireyc.append(cible[1]-(zone_princ.coords(i)[1]))
                if centaines>=20:
                    rang=0
                    for j in (objets_centaines):
                        zone_princ.move(j,trajectoirexc[rang],trajectoireyc[rang])
                        rang=rang+1
                if centaines<20:
                    for j in range (30):
                        rang=0
                        for k in (objets_centaines):
                            zone_princ.move(k,trajectoirexc[rang]/30,trajectoireyc[rang]/30)
                            rang=rang+1
                            zone_princ.update()
            if objet=="millier" or (objet=="tout" and int(nbcolonnes)>3):
                x1, x2, y1, y2 = coordshasard("millier")
                trajectoirexm = []
                trajectoireym = []
                for i in (objets_milliers):
                    xobjet = randint(x1, x2)
                    yobjet = randint(y1, y2)
                    cible=xobjet,yobjet
                    trajectoirexm.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoireym.append(cible[1]-(zone_princ.coords(i)[1]))
                if milliers>=20:
                    rang=0
                    for j in (objets_milliers):
                        zone_princ.move(j,trajectoirexm[rang],trajectoireym[rang])
                        rang=rang+1
                if milliers<20:
                    for j in range (30):
                        rang=0
                        for k in (objets_milliers):
                            zone_princ.move(k,trajectoirexm[rang]/30,trajectoireym[rang]/30)
                            rang=rang+1
                            zone_princ.update()
            ok=1
    def tirage(self):
    	global interg,interu,interd,interc,interm
    	if lock==0:
    		interg=interd=interd=interc=interm=interu=0
    		for i in (compteur_unites,compteur_dizaines,compteur_centaines,compteur_milliers,compteur):
    			i.place_forget()
    		for i in (choix_compteur,aff_compteur_unite,aff_compteur_dizaine,aff_compteur_millier,aff_compteur_centaine):
    			i.configure(image=img_oeil_inactif)
    			reset("tout")
    		for i in range(randint(0,max_u.get())):
    			cree("unite",1,"normal")
    		for i in range(randint(0,max_d.get())):
    			cree("dizaine",10,"normal")
    		if nb>2:
    			for i in range(randint(0,max_c.get())):
    				cree("centaine",100,"normal")
    		if nb>3:
    			for i in range(randint(0,max_m.get())):
    				cree("millier",1000,"normal")
    
    
    #Mise à jour des affichages des compteurs
    def maj():
        global tropde, nombre
        nb=int(nbcolonnes)
        nombre=(1000*milliers)+(100*centaines)+(10*dizaines)+unites
        if unites>9 or (dizaines>9 and nb>2) or (centaines>9 and nb>3):
            if unites>9:
                zone_princ.itemconfigure("unites", width=2,outline="red")
                compteur.configure(image=img_verifie)
            else:
                zone_princ.itemconfigure("unites", width=0, outline="black")
            if dizaines>9 and nb>2:
                zone_princ.itemconfigure("dizaines", width=2, outline="red")
                compteur.configure(image=img_verifie)
            else:
                zone_princ.itemconfigure("dizaines", width=0, outline="black")
            if centaines>9 and nb>3:
                zone_princ.itemconfigure("centaines", width=2, outline="red")
                compteur.configure(image=img_verifie)
            else:
                zone_princ.itemconfigure("centaines", width=0, outline="black")
        else:
            if unites<10:
                zone_princ.itemconfigure("unites", width=0, outline="black")
            if dizaines<10:
                zone_princ.itemconfigure("dizaines", width=0, outline="black")
            if centaines<10:
                zone_princ.itemconfigure("centaines", width=0, outline="black")
            compteur.configure(text=nombre, image='')
        if nb==4:
            compteur_milliers.configure(text=milliers)
        if nb>=3:
            compteur_centaines.configure(text=centaines)
        compteur_dizaines.configure(text=dizaines)
        compteur_unites.configure(text=unites)
    
    
    
    #Suppression d'un objet
    def suppr(objet):
        global nombre, milliers, centaines, dizaines, unites, u,d,c,m
        if objet=="millier" and milliers>0 and len(objets_milliers)>0:
            milliers = milliers - 1
            nombre = nombre - 1000
            zone_princ.delete(objets_milliers[-1])
            objets_milliers.pop()
        if objet=="centaine" and centaines>0 and len(objets_centaines)>0:
            centaines = centaines - 1
            nombre = nombre - 100
            zone_princ.delete(objets_centaines[-1])
            objets_centaines.pop()
        if objet=="dizaine" and dizaines>0 and len(objets_dizaines)>0:
            dizaines = dizaines - 1
            nombre = nombre - 10
            zone_princ.delete(objets_dizaines[-1])
            objets_dizaines.pop()
        if objet=="unite" and unites>0 and len(objets_unites)>0:
            unites= unites - 1
            nombre = nombre - 1
            zone_princ.delete(objets_unites[-1])
            objets_unites.pop()
        maj()
    
    #Suppression de tous les objets et remise à zéro
    def reset(objet):
        global nombre, milliers, centaines, dizaines, unites, objets_milliers, objets_centaines, objets_dizaines, objets_unites, dg,cg,mg
        if lock==0:
            if objet=="millier":
                zone_princ.delete("millier")
                objets_milliers.clear()
                milliers=0
            if objet=="centaine":
                zone_princ.delete("centaine")
                zone_princ.delete("millgauche")
                objets_centaines.clear()
                objets_millgauche.clear()
                centaines=0
                mg=0
            if objet=="dizaine":
                zone_princ.delete("dizaine")
                zone_princ.delete("centgauche")
                objets_dizaines.clear()
                objets_centgauche.clear()
                dizaines=0
                cg=0
            if objet=="unite":
                zone_princ.delete("unite")
                zone_princ.delete("dizgauche")
                objets_unites.clear()
                objets_dizgauche.clear()
                unites=0
                dg=0
            if objet=="tout":
                zone_princ.delete("millier")
                zone_princ.delete("centaine")
                zone_princ.delete("centgauche")
                zone_princ.delete("dizaine")
                zone_princ.delete("dizgauche")
                zone_princ.delete("unite")
                zone_princ.delete("millgauche")
                objets_milliers.clear()
                objets_centaines.clear()
                objets_dizaines.clear()
                objets_unites.clear()
                objets_dizgauche.clear()
                objets_centgauche.clear()
                objets_millgauche.clear()
                milliers=centaines=dizaines=unites=0
                mg=cg=dg=0
            nombre=1000*milliers+100*centaines+10*dizaines+unites
            maj()
    
    #Déplacement d'un objet
    def deplacement(objet,nb,dx,temps):
        if zone_princ.coords(objet)[1]<500:
            dy=2
        else:
            dy=-2
        for i in range(nb):
            zone_princ.move(objet, dx, dy)
            zone_princ.update()
            time.sleep(temps)
    
    #Calcul d'un trajet particulier
    def rel(type,id,rang,mode):
        coords=zone_princ.coords(id)
        return [(arrivee(type,rang,mode)[0])-coords[0],(arrivee(type,rang,mode)[1])-coords[1]]
    
    #Calcul de coordonnées cibles
    def arrivee(objet,rang,mode):
        global unites, dizaine, centaine, millier
        corr=0
        if objet=="millier":
            return [mean(positionsx) + (14 * (rang - 4)), mean(positionsy) - (14 * (rang - 4))]
        if objet=="centaine":
            return [mean(positionsx)-((larg_unite/3)*(rang-4)),mean(positionsy)+ ((larg_unite/3) * (rang - 4))]
        if objet=="dizaine":
             return moyx,moyy+(rang-5)*larg_unite
        if objet=="unite":
            if mode=="casse":
                return  coords_bouge[0]+2*larg_unite*((rang-2)-5*(rang//5)),coords_bouge[1]-larg_unite/2+larg_unite*2*int((rang)/5)
            else:
                return moyx+(rang-5)*larg_unite,moyy
    #Cassage (dégroupage d'un objet) et déplacement
    def casse(objet,compteur):
        global milliers,centaines,dizaines,unites, objets_milliers, nombre, m,c,d,u,ok, coords_bouge, rang_casse
        if compteur>0 and ok==1:
            compteur=compteur-1
            rang_casse=0
            positionsx = []
            positionsy = []
            trajectoirex= []
            trajectoirey= []
            if objet=="millier" and len(objets_milliers)>0:
                ok=0
                milliers=milliers-1
                zone_princ.tag_raise(objets_milliers[-1])
                if zone_princ.coords(objets_milliers[-1])[0]<liste_millier[1]+120:
                    dx=(larg_colonne/30)+4
                else:
                    dx=larg_colonne/30
                deplacement(objets_milliers[-1],30,dx,0.02)
                nombre=nombre-1000
                coords_bouge = zone_princ.coords(objets_milliers[-1])
                zone_princ.delete(objets_milliers[-1])
                objets_milliers.pop()
                for i in range(10):
                    rang_casse = rang_casse + 1
                    cree("centaine", 100,"bouge")
                zone_princ.update()
                time.sleep(0.6)
                zone_princ.update()
                time.sleep(0.6)
                ok=1
            if objet=="centaine" and len(objets_centaines)>0:
                ok=0
                centaines=centaines-1
                zone_princ.tag_raise(objets_centaines[-1])
                if zone_princ.coords(objets_centaines[-1])[0]<liste_centaine[1]+120:
                    dx=(larg_colonne/30)+4
                else:
                    dx=larg_colonne/30
                deplacement(objets_centaines[-1],30,dx,0.02)
                nombre=nombre-100
                coords_bouge = zone_princ.coords(objets_centaines[-1])
                zone_princ.delete(objets_centaines[-1])
                objets_centaines.pop()
                for i in range(10):
                    rang_casse = rang_casse + 1
                    cree("dizaine", 10,"bouge")
                zone_princ.update()
                time.sleep(0.6)
                zone_princ.update()
                time.sleep(0.6)
                ok=1
            if objet=="dizaine" and len(objets_dizaines)>0:
                ok=0
                dizaines=dizaines-1
                zone_princ.tag_raise(objets_dizaines[-1])
                if zone_princ.coords(objets_dizaines[-1])[0]<liste_dizaine[1]+120:
                    dx=(larg_colonne/30)+4
                else:
                    dx=larg_colonne/30
                deplacement(objets_dizaines[-1],30,dx,0.02)
                nombre=nombre-10
                coords_bouge = zone_princ.coords(objets_dizaines[-1])
                zone_princ.delete(objets_dizaines[-1])
                objets_dizaines.pop()
                for i in range(10):
                    rang_casse=rang_casse+1
                    cree("unite", 1,"bouge")
                rang = 0
                for i in (objets_unites[-10:]):
                    positionsx.append(zone_princ.coords(i)[0])
                    positionsy.append(zone_princ.coords(i)[1])
                for i in (objets_unites[-10:]):
                    trajectoirex.append(rel("unite", i, rang, "casse")[0])
                    trajectoirey.append(rel("unite", i, rang, "casse")[1])
                    rang = rang + 1
                for i in range(30):
                    rang = 0
                    for i in (objets_unites[-10:]):
                        zone_princ.move(i, trajectoirex[rang] / 30, trajectoirey[rang] / 30)
                        rang = rang + 1
                    zone_princ.update()
                    time.sleep(0.02)
                zone_princ.update()
                time.sleep(0.6)
            ok=1
    
    def gauche(objet,compteur):
        global unites, dizaines, centaines, milliers, dg, cg, mg, ok
        if ok==1:
            ok=0
            rangd=dizaines
            rangc=centaines
            rangm=milliers
            x1,x2,y1,y2=coordshasard(objet)
            trajectoirex = []
            trajectoirey = []
            if objet=="dizaine":
                for i in (objets_dizgauche):
                    if ordre.get()==1:
                        cible=rangement("dizaine",rangd)
                    else:
                        cible=randint(x1,x2), randint(y1,y2)
                    trajectoirex.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoirey.append(cible[1]-(zone_princ.coords(i)[1]))
                    rangd = rangd + 1
                if dizaines>=50:
                    rang=0
                    for j in (objets_dizgauche):
                        zone_princ.move(j,trajectoirex[rang],trajectoirey[rang])
                        zone_princ.update()
                        time.sleep(0.01)
                        rang=rang+1
                if dizaines<50:
                    for j in range (30):
                        rang=0
                        for k in (objets_dizgauche):
                            zone_princ.move(k,trajectoirex[rang]/30,trajectoirey[rang]/30)
                            rang=rang+1
                            zone_princ.update()
                            time.sleep(0.01)
                dizaines=dizaines+dg
                unites=unites-(10*dg)
                dg=0
                maj()
                zone_princ.itemconfigure('dizgauche',tags="dizaine")
                objets_dizaines.extend(objets_dizgauche)
                objets_dizgauche.clear()
            if objet=="centaine":
                for i in (objets_centgauche):
                    if ordre.get()==1:
                        cible=rangement("centaine",rangc)
                    else:
                        cible=randint(x1,x2), randint(y1,y2)
                    trajectoirex.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoirey.append(cible[1]-(zone_princ.coords(i)[1]))
                    rangc = rangc + 1
                if centaines>=50:
                    rang=0
                    for j in (objets_centgauche):
                        zone_princ.move(j,trajectoirex[rang],trajectoirey[rang])
                        rang=rang+1
                if centaines<50:
                    for j in range (30):
                        rang=0
                        for k in (objets_centgauche):
                            zone_princ.move(k,trajectoirex[rang]/30,trajectoirey[rang]/30)
                            rang=rang+1
                            zone_princ.update()
                centaines=centaines+cg
                dizaines=dizaines-(10*cg)
                cg=0
                maj()
                zone_princ.itemconfigure('centgauche',tags="centaine")
                objets_centaines.extend(objets_centgauche)
                objets_centgauche.clear()
            if objet=="millier":
                for i in (objets_millgauche):
                    if ordre.get()==1:
                        cible=rangement("millier",rangm)
                    else:
                        cible=randint(x1,x2), randint(y1,y2)
                    trajectoirex.append(cible[0]-(zone_princ.coords(i)[0]))
                    trajectoirey.append(cible[1]-(zone_princ.coords(i)[1]))
                    rangm = rangm + 1
                if milliers>=50:
                    rang=0
                    for j in (objets_millgauche):
                        zone_princ.move(j,trajectoirex[rang],trajectoirey[rang])
                        rang=rang+1
                if milliers<50:
                    for j in range (30):
                        rang=0
                        for k in (objets_millgauche):
                            zone_princ.move(k,trajectoirex[rang]/30,trajectoirey[rang]/30)
                            rang=rang+1
                            zone_princ.update()
                milliers=milliers+mg
                centaines=centaines-(10*mg)
                mg=0
                maj()
                zone_princ.itemconfigure('millgauche',tags="millier")
                objets_milliers.extend(objets_millgauche)
                objets_millgauche.clear()
        ok=1
    dg=cg=mg=0
    
    positionsx= []
    positionsy = []
    def groupe(objet,mode):
        global ok
        if ok==1:
            ok=0
            global unites,dizaines,centaines,milliers, dg,cg,mg, coords_groupe, positionsx, positionsy,moyx,moyy,objets,objets_unites
            trajectoirex = []
            trajectoirey = []
            positionsx= []
            positionsy = []
            if objet=="unite" and unites-10*dg>9:
                rang = 0
                if mode=="souris":
                    objets=uagrouper[-10:]
                else:
                    objets=objets_unites[-10:]
                for i in objets:
                    positionsx.append(zone_princ.coords(i)[0])
                    positionsy.append(zone_princ.coords(i)[1])
                moyx = mean(positionsx)
                moyy = mean(positionsy)
                for i in objets:
                    zone_princ.tag_raise(i)
                    trajectoirex.append(rel("unite", i, rang,"groupe")[0])
                    trajectoirey.append(rel("unite", i, rang,"groupe")[1])
                    rang = rang + 1
                for i in range(30):
                    rang = 0
                    for i in objets:
                        zone_princ.move(i, trajectoirex[rang] / 30, trajectoirey[rang] / 30)
                        rang = rang + 1
                    zone_princ.update()
                    time.sleep(0.02)
                zone_princ.update()
                time.sleep(0.02)
                coords_groupe = (zone_princ.coords(objets[-10]))[0], (zone_princ.coords(objets[-10]))[1]
                cree("dizaine", 10, "groupe")
                trajectoirey.clear()
                trajectoirey.clear()
                for i in objets:
                    objets_unites.remove(i)
                    zone_princ.delete(i)
                objets.clear()
                dg = dg + 1
                zone_princ.update()
                time.sleep(0.6)
            print(dizaines - 10 * cg)
            print(objet)
            if objet == "dizaine" and dizaines-10*cg > 9:
                print ("groupe dizaines")
                rang = 0
                if mode=="souris":
                    objets=dagrouper[-10:]
                else:
                    objets=objets_dizaines[-10:]
                for i in (objets):
                    positionsx.append(zone_princ.coords(i)[0])
                    positionsy.append(zone_princ.coords(i)[1])
                moyx = mean(positionsx)
                moyy = mean(positionsy)
                for i in reversed(objets_dizaines[-10:]):
                    zone_princ.tag_raise(i)
                for i in (objets):
                    trajectoirex.append(rel("dizaine", i, rang,"groupe")[0])
                    trajectoirey.append(rel("dizaine", i, rang,"groupe")[1])
                    rang = rang + 1
                for i in range(30):
                    rang = 0
                    for i in (objets):
                        zone_princ.move(i, (trajectoirex[rang]/30), ((trajectoirey[rang]+(30*cg)) / 30))
                        rang = rang + 1
                    zone_princ.update()
                    time.sleep(0.02)
                zone_princ.update()
                time.sleep(0.3)
                coords_groupe = moyx, moyy
                cree("centaine", 100, "groupe")
                for i in range(10):
                    zone_princ.delete(objets_dizaines[-1])
                    objets_dizaines.pop()
                cg = cg + 1
                zone_princ.update()
                time.sleep(0.6)
            if objet == "centaine" and centaines-10*mg > 9:
                rang = 0
                if mode=="souris":
                    objets=cagrouper[-10:]
                else:
                    objets=objets_centaines[-10:]
                for i in (objets):
                    positionsx.append(zone_princ.coords(i)[0])
                    positionsy.append(zone_princ.coords(i)[1])
                    moyx = mean(positionsx)
                    moyy = mean(positionsy)
                for i in (objets):
                    zone_princ.tag_raise(i)
                    trajectoirex.append(rel("centaine", i, rang,"groupe")[0])
                    trajectoirey.append(rel("centaine", i, rang,"groupe")[1])
                    rang = rang + 1
                for i in range(30):
                    rang = 0
                    for i in (objets):
                        zone_princ.move(i, (trajectoirex[rang]/30), ((trajectoirey[rang]+(30*cg)) / 30))
                        rang = rang + 1
                    zone_princ.update()
                    time.sleep(0.001)
                zone_princ.update()
                time.sleep(0.3)
                coords_groupe = (zone_princ.coords(objets_centaines[-10]))[0]-20,(zone_princ.coords(objets_centaines[-10]))[1]+20
                cree("millier", 1000, "groupe")
                for i in objets:
                    objets_centaines.remove(i)
                    zone_princ.delete(i)
                objets.clear()
                mg = mg + 1
                zone_princ.update()
                time.sleep(0.6)
        positionsy.clear()
        positionsx.clear()
        ok=1
    
    
    def degroupe(objet,mode):
        global coords_bouge,rang_casse,dg,cg,mg,objets_dizaines
        rang_casse=0
        trajectoirex=[]
        trajectoirey=[]
        if objet=="centaine" and (len(objets_millgauche)>0 or mode=="souris"):
            if mode=="souris":
                suppr=objetbouge
                objets_milliers.remove(objetbouge)
            else:
                suppr = objets_millgauche[-1]
                objets_millgauche.pop()
                mg = mg - 1
            coords_bouge=zone_princ.coords(suppr)
            if coords_bouge[1] < liste_centaine[1] + larg_dizaine/2:
                coords_bouge[1] = liste_centaine[1] + larg_dizaine
            if coords_bouge[1] > liste_centaine[3] - larg_dizaine/2:
                coords_bouge[1] = liste_centaine[3] - larg_dizaine
            if coords_bouge[0] < liste_centaine[0] + larg_dizaine/2:
                coords_bouge[0] = liste_centaine[0]+ larg_dizaine*1.2
            if coords_bouge[0] > liste_centaine[2] - larg_dizaine/2:
                coords_bouge[0] = liste_centaine[2]-larg_dizaine*1.1
            zone_princ.delete(suppr)
            for i in range(10):
                rang_casse = rang_casse + 1
                cree("centaine", 0,"degroupe")
        if objet=="dizaine" and (len(objets_centgauche)>0 or mode=="souris"):
            if mode=="souris":
                suppr=objetbouge
                objets_centaines.remove(objetbouge)
            else:
                suppr = objets_centgauche[-1]
                objets_centgauche.pop()
                cg = cg - 1
            coords_bouge=zone_princ.coords(suppr)
            if coords_bouge[1] < liste_dizaine[1] + 10 * larg_unite:
                coords_bouge[1] = liste_dizaine[1]+8*larg_unite
            if coords_bouge[1] > liste_dizaine[3] - 10 * larg_unite:
                coords_bouge[1] = liste_dizaine[3]-10*larg_unite
            if coords_bouge[0] < liste_dizaine[0] + larg_dizaine/2:
                coords_bouge[0] = liste_dizaine[0]+ larg_dizaine/2
            if coords_bouge[0] > liste_dizaine[2] - larg_dizaine/2:
                coords_bouge[0] = liste_dizaine[2]-larg_dizaine/2
            zone_princ.delete(suppr)
            cg=cg-1
            for i in range(10):
                rang_casse = rang_casse + 1
                cree("dizaine", 0,"degroupe")
        if objet=="unite" and (len(objets_dizgauche)>0 or mode=="souris"):
            if mode=="souris":
                suppr=objetbouge
                objets_dizaines.remove(objetbouge)
            else:
                suppr=objets_dizgauche[-1]
                objets_dizgauche.pop()
                dg = dg - 1
            coords_bouge = zone_princ.coords(suppr)
            print(liste_unite)
            print(coords_bouge)
            if coords_bouge[1] < liste_unite[1] + 2*larg_unite:
                print("coor1")
                coords_bouge[1] = liste_unite[1]+ 2*larg_unite
            if coords_bouge[1] > liste_unite[3] - 2*larg_unite:
                print("coor2")
                coords_bouge[1] = liste_unite[3]-2*larg_unite
    
            if coords_bouge[0] < liste_unite[0] + larg_dizaine/2:
                print("coor3")
                coords_bouge[0] = liste_unite[0]+ larg_dizaine/2
            if coords_bouge[0] > liste_unite[2] - larg_dizaine/2:
                print("coor4")
                coords_bouge[0] = liste_unite[2]-larg_dizaine/2
            zone_princ.delete(suppr)
    
            for i in range(10):
                rang_casse = rang_casse + 1
                cree("unite", 0,"degroupe")
            rang = 0
            for i in (objets_unites[-10:]):
                positionsx.append(zone_princ.coords(i)[0])
                positionsy.append(zone_princ.coords(i)[1])
            for i in (objets_unites[-10:]):
                trajectoirex.append(rel("unite", i, rang, "casse")[0])
                trajectoirey.append(rel("unite", i, rang, "casse")[1])
                rang = rang + 1
            for i in range(30):
                rang = 0
                for i in (objets_unites[-10:]):
                    zone_princ.move(i, trajectoirex[rang] / 30, trajectoirey[rang] / 30)
                    rang = rang + 1
                zone_princ.update()
                time.sleep(0.02)
    
    		
    
    
    #Spécial pour Windows
    def souris(event):
        if event.delta == -120:
            actionsouris(0)
        if event.delta == 120:
            actionsouris(1)
    
    #Action de la molette de la souris
    def actionsouris(mode):
        x = fenetre.winfo_pointerx() - fenetre.winfo_rootx() -105
        y = fenetre.winfo_pointery() - fenetre.winfo_rooty() -105
        if liste_unite[1]<y<liste_unite[3]:
            if liste_unite[0]<x<liste_unite[2]:
                if mode==1:
                    new("unite", 1, "normal")
                else:
                    man_suppr("unite")
            if liste_dizaine[0]<x<liste_dizaine[2]:
                if mode==1:
                    new("dizaine", 10, "normal")
                else:
                    man_suppr("dizaine")
            if nb>2:
                if liste_centaine[0]<x<liste_centaine[2]:
                    if mode==1:
                        new("centaine", 10, "normal")
                    else:
                        man_suppr("centaine")
            if nb>3:
                if liste_millier[0]<x<liste_millier[2]:
                    if mode==1:
                        new("millier", 1000, "normal")
                    else:
                        man_suppr("millier")
    
    def switch_images(self):
    	if lignes.get()==0:	
    		lignes.set(1)
    	if lignes.get()==1:
    		lignes.set(1)
    	change_images
    
    def retour(objet):
        print("retour")
        if objet in objets_unites or objet in objets_dizgauche:
            zone_princ.moveto(objet,centreu[0],centreu[1])
        if objet in objets_dizaines or objet in objets_centgauche:
             zone_princ.moveto(objet,centred[0],centred[1])
        if objet in objets_centaines or objet in objets_millgauche:
            print(centrec)
            zone_princ.moveto(objet,centrec[0],centrec[1])
        if objet in objets_milliers:
            zone_princ.moveto(objet,centrem[0],centrem[1])
    
    
    
    bouton_tirage=Button(zone_gauche, text="Au hasard", command=lambda:tirage("self"))
    bouton_tirage.grid(row=6, column=0,pady=4, columnspan=4)
    choixlignes=Checkbutton(zone_gauche, variable=lignes, onvalue = 1, offvalue = 0, text='Lignes', command=change_images)
    choixlignes.grid(row=10,column=0, sticky='w', pady=4, columnspan=4)
    choixcouleurs=Checkbutton(zone_gauche, variable=couleurs, onvalue = 1, offvalue = 0, text='Couleurs', command=change_images)
    choixcouleurs.grid(row=11,column=0, sticky='w', pady=4, columnspan=4)
    choixrange=Checkbutton(zone_gauche, variable=ordre, onvalue = 1, offvalue = 0, text='Ranger')
    choixrange.grid(row=12,column=0, sticky='w', pady=4, columnspan=4)
    
    boutons.append(bouton_tirage)
    
    
    def estdans(objet,zone):
        if zone[0]<zone_princ.coords(objet)[0]<zone[2] and zone[1]<zone_princ.coords(objet)[1]<zone[3]:
            return True
        else:
            return False
    
    DETECTION_CLIC_SUR_OBJET=False
    
    def Clic(event):
        global DETECTION_CLIC_SUR_OBJET, diffx, diffy, objetbouge, select, rectx, recty
        if ok==1:
            # position du pointeur de la souris
            X = event.x
            Y = event.y
            # coordonnées du rectangle qui encadre l'objet
            for i in [*objets_unites,*objets_dizaines,*objets_centaines,*objets_milliers,*objets_dizgauche,*objets_centgauche,*objets_millgauche]:
                [x1,y1,x2,y2] = zone_princ.bbox(i)
                if x1 < X < x2 and y1 < Y < y2:
                    DETECTION_CLIC_SUR_OBJET = 1
                    objetbouge=i
                    zone_princ.tag_raise(objetbouge)
                    #calcul de la position relative du pointeur au moment du clic
                    diffx=X-x1
                    diffy=Y-y1
            if DETECTION_CLIC_SUR_OBJET==0:
                select=zone_princ.create_rectangle(X,Y,X,Y,outline="blue", width=3)
                rectx=X
                recty=Y
                DETECTION_CLIC_SUR_OBJET = 2
    
    def Drag(event):
        global select, ok
        """ Gestion de l'événement bouton gauche enfoncé """
        if DETECTION_CLIC_SUR_OBJET==1 and ok==1:
            ok=0
            X = event.x
            Y = event.y
            # mise à jour de la position de l'objet
            zone_princ.moveto(objetbouge, X-diffx,Y-diffy)
            ok=1
        elif DETECTION_CLIC_SUR_OBJET == 2 and ok==1:
            ok=0
            X = event.x
            Y = event.y
            zone_princ.delete(select)
            select=zone_princ.create_rectangle(rectx,recty,X,Y,outline="blue", width=3)
            ok=1
    
    uagrouper=[]
    dagrouper=[]
    cagrouper=[]
    def End(event):
    
        global DETECTION_CLIC_SUR_OBJET, objetbouge, dizaines, unites, centaines, milliers, select, agrouper,dg,cg,mg
        if DETECTION_CLIC_SUR_OBJET==1:
            if estdans(objetbouge,liste_unite):
                if objetbouge in objets_dizaines:
                    dizaines=dizaines-1
                    unites=unites+10
                    degroupe("unite","souris")
                    if ordre.get()==1:
                        print("ordre")
                        action_range("unite")
                elif objetbouge not in objets_unites and objetbouge not in objets_dizgauche:
                    retour(objetbouge)
            elif estdans(objetbouge,liste_dizaine):
                if objetbouge in objets_dizgauche:
                    dizaines = dizaines + 1
                    unites = unites - 10
                    dg = dg - 1
                    objets_dizaines.append(objetbouge)
                    objets_dizgauche.remove(objetbouge)
                    maj()
                elif objetbouge in objets_centaines:
                    centaines = centaines - 1
                    dizaines = dizaines + 10
                    degroupe("dizaine", "souris")
                    if ordre.get() == 1:
                        print("ordre")
                        action_range("dizaine")
                elif objetbouge not in objets_dizaines and objetbouge not in objets_centgauche:
                    retour(objetbouge)
            elif int(nbcolonnes)>2 and estdans(objetbouge, liste_centaine):
                print("depose zone centaines")
                if objetbouge in objets_centgauche:
                    centaines = centaines + 1
                    dizaines = dizaines - 10
                    cg = cg - 1
                    objets_centaines.append(objetbouge)
                    objets_centgauche.remove(objetbouge)
                    maj()
                elif objetbouge in objets_milliers:
                    milliers = milliers - 1
                    centaines = centaines + 10
                    degroupe("centaine", "souris")
                    if ordre.get() == 1:
                        print("ordre")
                        action_range("centaine")
                elif objetbouge not in objets_centaines and objetbouge not in objets_millgauche:
                    retour(objetbouge)
            elif int(nbcolonnes)>3 and estdans(objetbouge, liste_millier):
                milliers = milliers + 1
                centaines = centaines - 10
                mg = mg - 1
                objets_milliers.append(objetbouge)
                objets_millgauche.remove(objetbouge)
                maj()
            elif objetbouge not in objets_milliers:
                retour(objetbouge)
            else:
                retour(objetbouge)
            DETECTION_CLIC_SUR_OBJET=0
    
        if DETECTION_CLIC_SUR_OBJET == 2 and ok==1:
            for i in objets_unites:
                if zone_princ.coords(select)[0]<zone_princ.coords(i)[0]<zone_princ.coords(select)[2] and zone_princ.coords(select)[1]<zone_princ.coords(i)[1]<zone_princ.coords(select)[3]:
                    uagrouper.append(i)
            for j in objets_dizaines:
                if zone_princ.coords(select)[0]<zone_princ.coords(j)[0]<zone_princ.coords(select)[2] and zone_princ.coords(select)[1]<zone_princ.coords(j)[1]<zone_princ.coords(select)[3]:
                    dagrouper.append(j)
            for k in objets_centaines:
                if zone_princ.coords(select)[0]<zone_princ.coords(k)[0]<zone_princ.coords(select)[2] and zone_princ.coords(select)[1]<zone_princ.coords(k)[1]<zone_princ.coords(select)[3]:
                    cagrouper.append(k)
            zone_princ.delete(select)
            if len(uagrouper)>=10:
                groupe("unite","souris")
                uagrouper.clear()
                if ordre.get()==1:
                    action_range("unite")
            if len(dagrouper)>=10:
                groupe("dizaine","souris")
                dagrouper.clear()
                if ordre.get()==1:
                    action_range("dizaine")
            if len(cagrouper)>=10:
                print ("groupe centaines")
                groupe("centaine","souris")
                cagrouper.clear()
                if ordre.get()==1:
                    action_range("centaine")
            uagrouper.clear()
            dagrouper.clear()
            cagrouper.clear()
            DETECTION_CLIC_SUR_OBJET =0
    
    
    
    #Appuis sur les touches
    fenetre.bind_all('<u>', lambda event: new("unite", 1,"normal"))
    fenetre.bind_all('<Control-u>', lambda event: suppr("unite"))
    
    fenetre.bind_all('<d>', lambda event: new("dizaine", 10,"normal"))
    fenetre.bind_all('<Control-d>', lambda event: suppr("dizaine"))
    
    fenetre.bind_all('<c>', lambda event: new("centaine", 100,"normal"))
    fenetre.bind_all('<Control-c>', lambda event: suppr("centaine"))
    
    fenetre.bind_all('<m>', lambda event: new("millier", 1000,"normal"))
    fenetre.bind_all('<Control-m>', lambda event: suppr("millier"))
    
    fenetre.bind_all('<r>', lambda event: action_range("tout"))
    fenetre.bind_all('<t>',tirage)
    
    fenetre.bind_all('<v>', lambda event: affichage_compteur(choix_compteur,compteur,interg))
    
    fenetre.bind_all('<space>', lambda event: reset("tout"))
    fenetre.bind_all('<b>',verr)
    fenetre.bind_all('<l>',switch_images)
    fenetre.bind_all('<Button-4>',lambda event: actionsouris(1))
    fenetre.bind_all('<Button-5>',lambda event: actionsouris(0))
    fenetre.bind_all('<MouseWheel>',souris)
    fenetre.bind_all('<Escape>',lambda event: fenetre.destroy())
    
    #événements souris
    zone_princ.bind('<Button-1>',Clic) # évévement clic gauche (press)
    zone_princ.bind('<B1-Motion>',Drag) # événement bouton gauche enfoncé (hold down)
    zone_princ.bind('<ButtonRelease-1>',End) # événement bouton gauche relâché (hold down)
    
    
    #Boucle principale
    fenetre.mainloop()
    
    
    
    
    
    




    • Partager sur Facebook
    • Partager sur Twitter
      1 février 2023 à 15:44:58

      ArnaudJouski a écrit:

      Qu'en pensez-vous ?

      Un "gros" programme est la composition de fonctionnalités qui ne demandent que quelques lignes de code pour être réalisées. Une fois qu'on en maîtrise la mécanique, on peut composer ce petit bout avec le reste.

      Un premier boulot est donc de travailler sur les détails qui paraissent difficiles (et qui le sont sans doute) pour voir comment on va pouvoir gérer la ou les contraintes.

      Par exemple:

      ArnaudJouski a écrit:

      comme je ne sais pas modifier les dimensions de mon rectangle "select", je le supprime et le re-crée à chaque déplacement de souris, j'ai conscience que c'est consommateur de ressources mais je ne sais pas faire autrement.

      Faire un exemple en quelques lignes pour se concentrer sur ce sujet... est le premier travail à faire (et ça produit un code facile à échanger en cas de problème). 

      Après c'est vous qui voyez mais au plus le code est gros au plus celui qui sera tenté de le lire voudra le ré-écrire et oubliera un peu la question posée au départ... Et au plus le code est gros au moins il y aura de candidats pour vous aider.

      • Partager sur Facebook
      • Partager sur Twitter
        1 février 2023 à 17:10:12

        Je ne suis pas sûr que tkinter soit le meilleur choix pour ce genre de chose.
        • Partager sur Facebook
        • Partager sur Twitter

        Python c'est bon, mangez-en. 

        Anonyme
          1 février 2023 à 18:26:01

          Bonjour !

          Faut apprendre à synthétiser et reproduire un code minimal !

          import tkinter as tk
          
          def drag(event):
              rect = canvas.find_closest(event.x, event.y)
              canvas.moveto(rect, event.x, event.y)
          
          root = tk.Tk()
          canvas = tk.Canvas()
          rect1 = canvas.create_rectangle(50,50,100,100,outline ="black",fill ="red",width = 5)
          rect2 = canvas.create_rectangle(150,150,200,200,outline ="black",fill ="green",width = 5)
          canvas.pack()
          canvas.bind('<B1-Motion>', drag)
          root.mainloop()
          




          • Partager sur Facebook
          • Partager sur Twitter
            1 février 2023 à 21:03:30

            ErispoeLeNarvalo a écrit:

            Bonjour !

            Faut apprendre à synthétiser et reproduire un code minimal !

            import tkinter as tk
            
            def drag(event):
                rect = canvas.find_closest(event.x, event.y)
                canvas.moveto(rect, event.x, event.y)
            
            root = tk.Tk()
            canvas = tk.Canvas()
            rect1 = canvas.create_rectangle(50,50,100,100,outline ="black",fill ="red",width = 5)
            rect2 = canvas.create_rectangle(150,150,200,200,outline ="black",fill ="green",width = 5)
            canvas.pack()
            canvas.bind('<B1-Motion>', drag)
            root.mainloop()
            

            Ah mais c'est génial ça, find_closest 🙂 Merci beaucoup, je pensais pas que ça existait, d'où mon bricolage pour le déterminer.

            Et oui, c'est vrai qu'on peut utiliser directement la veleur de event, pas obligé de le stocker dans une variable.

            J'ai quand même besoin de dissocier l'événement "clic" et "motion" car je déplace des objets quand je clique dessus et je fais tracer un rectangle quand on clique ailleurs.







            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              2 février 2023 à 18:14:20

              Et oui il faut ouvrir la doc !

              https://tkdocs.com/shipman/canvas-methods.html

              import tkinter as tk
              
              def drag(event):
                  rect = canvas.find_closest(event.x, event.y)
                  canvas.moveto(rect, event.x, event.y)
              
              def pencil_down(event):
                  rects.append( canvas.create_rectangle(event.x,event.y,event.x+5,event.y+5,outline ="black",fill ="cyan",width = 5) )
              
              def pencil_move(event):
                  rect = rects[-1]
                  x0, y0, x1, y1 = canvas.coords(rect)
                  canvas.coords(rect, x0, y0, event.x, event.y)
              
              root = tk.Tk()
              canvas = tk.Canvas()
              rects = []
              rects.append( canvas.create_rectangle(50,50,100,100,outline ="black",fill ="red",width = 5) )
              rects.append( canvas.create_rectangle(150,150,200,200,outline ="black",fill ="green",width = 5) )
              canvas.pack()
              canvas.bind('<B1-Motion>', drag)
              canvas.bind('<Shift-Button-1>', pencil_down)
              canvas.bind('<Shift-B1-Motion>', pencil_move)
              root.mainloop()

              Pressez shift pour dessiner un rectangle avec la souris.



              • Partager sur Facebook
              • Partager sur Twitter
                6 février 2023 à 17:27:19

                OK j'ai compris.

                Donc

                 canvas.coords(rect, x0, y0, event.x, event.y)

                pour mettre à jour la taille du rectangle au lieu de le supprimer et le re-créer à chaque fois.

                Merci

                • Partager sur Facebook
                • Partager sur Twitter

                Améliorer le déplacmeent d'objets à la souris

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown