Partage
  • Partager sur Facebook
  • Partager sur Twitter

Supprimer des objets de même type

    13 janvier 2023 à 9:25:13

    Rebonjour,

    Suite de mon programme, avec une nouvelle problématique donc je crée un nouveau sujet.

    Je souhaiterais au moyens de boutons "reset milliers", "reset centaines" ... supprimer tous les objets correspondants.

    Donc je les taggue à la création :

        zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img, tags=objet)
    

    puis je les supprime (enfin j'essaie) :

    reset_millier=Button(zone_haut, text="reset milliers", command=zone_princ.delete('millier'))

    Mais il semble que tags=objet n'attribue pas la valeur de "objet" qui entre en argument dans la fonction :

    def cree(objet,img):
        #On récupère les coordonnées de la colonne correspondante
        if objet=="millier":
            liste_coords=liste_millier
        if objet=="centaine":
            liste_coords=liste_centaine
        if objet=="dizaine":
            liste_coords=liste_dizaine
        if objet=="unite":
            liste_coords=liste_unite
        #On attribue des positions maxi
        x1=int(liste_coords[0]+60)
        x2=int(liste_coords[2]-60)
        y1=int(liste_coords[1]+60)
        y2=int(liste_coords[3]-60)
        #On crée l'objet à une position aléatoire à l'intérieur des positions maxi et on le taggue avec le type d'objet
        zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img, tags=objet)

    J'ai essayé avec (en l'identifiant en début de ligne)

        objet=zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img)
    

    mais ça ne fonctionne pas non plus.

    Voici mon code et une copie d'écran (je sais que j'ai un problème de grid sur les boutons aussi 🙂)

    Où est-ce que j'ai faux ?

    Merci encore




    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from tkinter import *
    from random import *
    
    #Création de la fenêtre
    
    fenetre = Tk()
    larg=fenetre.winfo_screenwidth()-100
    haut=fenetre.winfo_screenheight()-100
    fenetre.title("Numération")
    fenetre.geometry(f"{larg}x{haut}+0+0")
    
    #Cré"ation des cadres
    zone_haut=Frame(fenetre, height=100, relief="sunken").grid(row=0,column=0)
    zone_gauche=Frame(fenetre, width=100, height=haut-100, relief="raised").grid(row=1,column=0)
    zone_princ=Canvas(fenetre, width=larg-100, height=haut-100, bg="white")
    zone_princ.grid(row=1,column=1)
    
    #Variables
    
    larg_canvas=larg-100
    haut_canvas=haut-100
    marge=50
    larg_colonne=(larg_canvas-(5*marge))/4
    posx=posy=marge
    tagobjet=0
    
    #Création des zones milliers, centaines, dizaines, unités
    
    for i in ("milliers","centaines","dizaines","unites"):
        i=zone_princ.create_rectangle(posx,posy,larg_colonne+posx,haut_canvas-marge, tags=f"{i}")
        posx=posx+marge+larg_colonne
    
    #Création de listes des coordonnées des coins des rectangles
    
    liste_millier=zone_princ.coords("milliers")
    liste_centaine=zone_princ.coords("centaines")
    liste_dizaine=zone_princ.coords("dizaines")
    liste_unite=zone_princ.coords("unites")
    
    #Déclaration des images
    
    img_unite=PhotoImage(file="images/unite.png")
    img_dizaine=PhotoImage(file="images/dizaine.png")
    img_centaine=PhotoImage(file="images/centaine.png")
    img_millier=PhotoImage(file="images/millier.png")
    
    #Boucle de création d'une image
    
    def cree(objet,img):
        #On récupère les coordonnées de la colonne correspondante
        if objet=="millier":
            liste_coords=liste_millier
        if objet=="centaine":
            liste_coords=liste_centaine
        if objet=="dizaine":
            liste_coords=liste_dizaine
        if objet=="unite":
            liste_coords=liste_unite
        #On attribue des positions maxi
        x1=int(liste_coords[0]+60)
        x2=int(liste_coords[2]-60)
        y1=int(liste_coords[1]+60)
        y2=int(liste_coords[3]-60)
        #On crée l'objet à une position aléatoire à l'intérieur des positions maxi et on le taggue avec le type d'objet
        zone_princ.create_image(randint(x1,x2), randint(y1,y2), image=img, tags=objet)
    
    
    #Boutons
    
    reset_millier=Button(zone_haut, text="reset milliers", command=zone_princ.delete('millier'))
    reset_centaine=Button(zone_haut, text="reset centaines", command=zone_princ.delete('centaine'))
    reset_dizaine=Button(zone_haut, text="reset dizaines", command=zone_princ.delete('dizaine'))
    reset_unite=Button(zone_haut, text="reset unités", command=zone_princ.delete('unite'))
    
    reset_millier.grid(row=0,column=0)
    reset_centaine.grid(row=0,column=1)
    reset_dizaine.grid(row=0,column=2)
    reset_unite.grid(row=0,column=3)
    
    
    #Appuis sur les touches
    
    fenetre.bind_all('<u>', lambda event: cree("unite",img_unite))
    fenetre.bind_all('<d>', lambda event: cree("dizaine",img_dizaine))
    fenetre.bind_all('<c>', lambda event: cree("centaine",img_centaine))
    fenetre.bind_all('<m>', lambda event: cree("millier",img_millier))
    
    
    fenetre.mainloop()
    
    
    
    
    
    

    Edit : j'ai trouvé une façon, ça fonctionne comme ça :

    def suppr(objet):
        global nombre
        if objet=="millier":
            zone_princ.delete("millier")
        if objet=="centaine":
            zone_princ.delete("centaine")
        if objet=="dizaine":
            zone_princ.delete("dizaine")
        if objet=="unite":
            zone_princ.delete("unite")
    
    #Boutons
    
    reset_millier=Button(zone_haut, text="reset milliers", command=lambda:suppr("millier"))
    reset_centaine=Button(zone_haut, text="reset centaines", command=lambda:suppr("centaine"))
    reset_dizaine=Button(zone_haut, text="reset dizaines", command=lambda:suppr("dizaine"))
    reset_unite=Button(zone_haut, text="reset unités", command=lambda:suppr("unite"))
    
    reset_millier.grid(row=0,column=0)
    reset_centaine.grid(row=0,column=1)
    reset_dizaine.grid(row=0,column=2)
    reset_unite.grid(row=0,column=3)




    -
    Edité par ArnaudJouski 13 janvier 2023 à 11:04:02

    • Partager sur Facebook
    • Partager sur Twitter
      13 janvier 2023 à 12:20:57

      from tkinter import Tk, Canvas, Button
      
      
      def reset(canvas: Canvas, tag_name):
          def wrap():
              canvas.delete(tag_name)
          return wrap
      
      
      root = Tk()
      zone_princ=Canvas(root, width=100, height=100, bg="white")
      zone_princ.pack()
      
      rect = zone_princ.create_rectangle(5, 5, 40, 50, tags="millier")
      
      button = Button(root, text="suppr item", command=reset(zone_princ, "millier"))
      button.pack()
      
      root.mainloop()
      
      Un truc comme ça ?
      • Partager sur Facebook
      • Partager sur Twitter

      Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
      La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

        24 janvier 2023 à 13:27:12 - Message modéré pour le motif suivant : Merci d'écrire en français


          28 janvier 2023 à 2:57:10

          Salut,

          Effectivement, vous devez utiliser la methode anonyne "lambda". Sans celle-ci, les "méthodes" sont automatiquement exécuté, lorsque le script commence. Vous le voyez peut-être pas, puisque vos rectangles sont vides au début, mais les méthodes sont exécuté au début. Ce qui vide les rectangles, dès le commencement.

          Ensuite, lorsque vous appuyez sur les buttons "reset", rien ne se passe. puisqu'ils sont déjà exécutés.

          reset_millier = Button(zone_haut, text="reset milliers", command=lambda: zone_princ.delete('millier'))
          reset_centaine = Button(zone_haut, text="reset centaines", command=lambda: zone_princ.delete('centaine'))
          reset_dizaine = Button(zone_haut, text="reset dizaines", command=lambda: zone_princ.delete('dizaine'))
          reset_unite = Button(zone_haut, text="reset unités", command=lambda: zone_princ.delete('unite'))
          • Partager sur Facebook
          • Partager sur Twitter
            31 janvier 2023 à 17:09:20

            Oui voilà avec lambda.

            Merci

            • Partager sur Facebook
            • Partager sur Twitter
              31 janvier 2023 à 17:42:08

              nolimitech a écrit:

              Effectivement, vous devez utiliser la methode anonyne "lambda". Sans celle-ci, les "méthodes" sont automatiquement exécuté, lorsque le script commence.

              Non ce n'est pas une obligation !

              • Partager sur Facebook
              • Partager sur Twitter

              Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
              La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

                2 février 2023 à 1:37:33

                @fred1599, que voulez-vous dire? C'est vrai, qu'il ne faut pas utiliser de méthodes avec les parenthèses (En donnant des arguments), sinon le script exécute ces méthodes au commencement du script.... Donc, c'est soit sans parenthèse, donc sans arguments, ou bien avec lambda...

                Qu'es-ce qui est faux?

                Voici un exemple, et dit moi ce qui n'est pas une obligation? 

                import tkinter as tk
                
                
                def callback1():
                    print("Callback #1")
                
                
                def callback2(*args, **kwargs):
                    print("Callback #2", *args, **kwargs)
                
                
                root = tk.Tk()
                
                btn1 = tk.Button(root, text="Button #1", command=callback1)
                btn1.pack()
                
                btn2 = tk.Button(root, text="Button #2", command=callback2)
                btn2.pack()
                
                btn3 = tk.Button(root, text="Button #3", command=callback2("foo", "bar"))
                btn3.pack()
                
                btn4 = tk.Button(root, text="Button #4", command=lambda *a, **kw: callback2("foo", "bar"))
                btn4.pack()
                
                root.mainloop()

                Aussitôt, que l'on commence le script, le "callback2" du "btn3", est activer. Ensuite, il ne fonctionne plus!!!

                • Partager sur Facebook
                • Partager sur Twitter
                  2 février 2023 à 7:45:17

                  nolimitech a écrit:

                  @fred1599, que voulez-vous dire?

                  Ce n'est pas faux, je contredis juste le fait qu'on doit utiliser lambda pour créer son callback sur un bouton Tkinter.

                  lambda n'est que du sucre syntaxique et qui puis est un mot clé pas très apprécié pour son manque de lisibilité (enfin si la ligne lambda est simpliste et pas alambiqué, ça passe), voir PEP8.

                  PEP8

                  Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier:

                  # Correct: def f(x): return 2*x

                  # Wrong: f = lambda x: 2*x

                  The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic ‘’. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)

                  On peut faire autrement, un callback n'est qu'un objet fonction en python.

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
                  La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

                    2 février 2023 à 11:33:41

                    fred1599 a écrit:

                    nolimitech a écrit:

                    @fred1599, que voulez-vous dire?

                    Ce n'est pas faux, je contredis juste le fait qu'on doit utiliser lambda pour créer son callback sur un bouton Tkinter.

                    Le propos de nolimitech porte surtout sur l'erreur courante  qui consiste à écrire l'appel au lieu callable, après que ce callable soit un lambda ou une fonction def n'était pas dans son propos me semble-t-il surtout que le PO a rectifié avec des lambda dans on edit donc il doit faire allusion à cela.

                    fred1599 a écrit:

                    PEP8

                    Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier:

                    # Correct: def f(x): return 2*x

                    # Wrong: f = lambda x: 2*x

                    The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic ‘’. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)


                    On en revient au sens initial d'une lambda : une fonction anonyme.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 février 2023 à 12:32:23

                      PascalOrtiz a écrit:

                      fred1599 a écrit:

                      nolimitech a écrit:

                      @fred1599, que voulez-vous dire?

                      Ce n'est pas faux, je contredis juste le fait qu'on doit utiliser lambda pour créer son callback sur un bouton Tkinter.

                      Le propos de nolimitech porte surtout sur l'erreur courante  qui consiste à écrire l'appel au lieu callable, après que ce callable soit un lambda ou une fonction def n'était pas dans son propos me semble-t-il surtout que le PO a rectifié avec des lambda dans on edit donc il doit faire allusion à cela.

                      fred1599 a écrit:

                      PEP8

                      Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier:

                      # Correct: def f(x): return 2*x

                      # Wrong: f = lambda x: 2*x

                      The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic ‘’. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)


                      On en revient au sens initial d'une lambda : une fonction anonyme.


                      Je n'ai pas tout compris, mais pour la première remarque, le PO utilisait des fonctions standards, pas des lambdas (c'est la proposition de @nomilitech), et ce que j'exprime c'est que ce qui est proposé par le PO est possible, voir mon code exemple en 1ère réponse.

                      Pour la 2ème, rien compris !

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
                      La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

                      Supprimer des objets de même type

                      × 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