IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tkinter Python Discussion :

Supprimer des lignes et des colonnes d'une grille


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Par défaut Supprimer des lignes et des colonnes d'une grille
    Bonjour, j'ai crée une grille qui contient des labels encapsulés dans des rectangles.
    Je voudrais que lorsque on clique sur un label, la colonne et la ligne qui le contienne soit supprimées.
    Je sais supprimer ces lignes et ces colonnes lorsque la grille contient uniquement des rectangles vides.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    import tkinter as tk
     
    DIM_GRILLE = (8, 8)
    DIM_CASE = 50
    DIM_LIGNE = 1
     
    DIM_CANEVAS = (
        DIM_GRILLE[0]*DIM_CASE + (DIM_GRILLE[0]+1)*DIM_LIGNE,
        DIM_GRILLE[1]*DIM_CASE + (DIM_GRILLE[1]+1)*DIM_LIGNE
    )
     
     
    def destroyer(evt) :
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        if not r :
            return
        rid = r[0]
     
        # Récupération des index ligne et colonne contenant l'id rectangle
        for il, ligne in enumerate(items) :
            if rid in ligne :
                ic = ligne.index(rid)
                break
     
        # Suppressions de la ligne et colonne du tableau items
        # Et suppression dans le canevas
        lid = items.pop(il)
        for oid in lid :
            can.delete(oid)
     
        for ligne in items :
            oid = ligne.pop(ic)
            can.delete(oid)
     
        if not any(items) :
            # Plus rien à faire, le tableau d'items est vide.
            return
     
        nombreLignes = len(items)
        nombreColonnes = len(items[0])
     
        # Calculs des dimensions de chaque lignes
        # Soustraction des lignes de la hauteur du canevas
        hautCan = DIM_CANEVAS[1] - (nombreLignes+1) * DIM_LIGNE
        # Répartition de la hauteur
        hauteurs = [hautCan // nombreLignes] * nombreLignes
        for i in range(hautCan % nombreLignes) :
            hauteurs[i] += 1
     
        # Calculs des dimensions de chaque colonnes
        largCan = DIM_CANEVAS[0] - (nombreColonnes+1) * DIM_LIGNE
        largeurs = [largCan // nombreColonnes] * nombreColonnes
        for i in range(largCan % nombreColonnes) :
            largeurs[i] += 1
     
        # Mises à jour des dimensions
        ih = 0
        y = DIM_LIGNE
        for ligne in items :
            il = 0
            x = DIM_LIGNE
            for oid in ligne :
                can.coords(oid, x, y, x+largeurs[il], y+hauteurs[ih])
                x += largeurs[il] + DIM_LIGNE
                il += 1
            ih += 1
            try :
                y += hauteurs[ih] + DIM_LIGNE
            except IndexError :
                # Dernier tour de boucle
                break
     
     
    fenetre = tk.Tk()
     
    can = tk.Canvas(
        fenetre,
        width=DIM_CANEVAS[0],
        height=DIM_CANEVAS[1],
        bg='black',
        highlightthickness=0,
    )
    can.grid()
     
    items = []
    colors = ['red', 'yellow']
    y = DIM_LIGNE
     
    for ligne in range(DIM_GRILLE[1]) :
        x = DIM_LIGNE
        ids = []
        colors.reverse()
        for col in range(DIM_GRILLE[0]) :
            i = can.create_rectangle(
                x, y, x+DIM_CASE, y+DIM_CASE,
                fill=colors[col % 2],
                width=0,
                # tags='l{} c{}'.format(ligne, col),
            )
            ids.append(i)
            x += DIM_CASE + DIM_LIGNE
        items.append(ids)
        y += DIM_CASE + DIM_LIGNE
     
    can.bind('<Button-1>', destroyer)
     
    fenetre.mainloop()
    Pour l'instant je bloque avec les labels. Je suppose qu'il faut remplacer ids.append(i) par ids.append((i,text_item)) mais je rencontre ensuite un problème dans la fonction destroyer. Pourriez-vous m'aider à le résoudre, svp. Je vous en remercie d'avance.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    import tkinter as tk
     
    DIM_GRILLE = (20, 20)
    DIM_CASEL = 30
    DIM_CASEH = 20
    DIM_LIGNE = 1
     
    DIM_CANEVAS = (
        DIM_GRILLE[0]*DIM_CASEL + (DIM_GRILLE[0]+1)*DIM_LIGNE,
        DIM_GRILLE[1]*DIM_CASEH + (DIM_GRILLE[1]+1)*DIM_LIGNE
    )
     
     
    def destroyer(evt) :
     
        #print(F[2])
     
        print (can.itemcget(items[0], 'fill'))
     
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        if not r :
            return
        rid = r[0]
     
        print(r)
     
        myColor = can.itemcget(rid,'fill')
        print(myColor)
     
        if myColor == "yellow":
     
            # Récupération des index ligne et colonne contenant l'id rectangle
            for il, ligne in enumerate(items[0]) :
                if rid in ligne :
                    ic = ligne.index(rid)
                    print(ic)
                    break
     
            # Suppressions de la ligne et colonne du tableau items
            # Et suppression dans le canevas
            lid = items[0].pop(il)
            for oid in lid :
                can.delete(oid)
     
            for ligne in items[0] :
                oid = ligne.pop(ic)
                can.delete(oid)
     
            if not any(items) :
                # Plus rien à faire, le tableau d'items est vide.
                return
     
            nombreLignes = len(items)
            nombreColonnes = len(items[0])
     
            # Calculs des dimensions de chaque lignes
            # Soustraction des lignes de la hauteur du canevas
            hautCan = DIM_CANEVAS[1] - (nombreLignes+1) * DIM_LIGNE
            # Répartition de la hauteur
            hauteurs = [hautCan // nombreLignes] * nombreLignes
            for i in range(hautCan % nombreLignes) :
                hauteurs[i] += 1
     
            # Calculs des dimensions de chaque colonnes
            largCan = DIM_CANEVAS[0] - (nombreColonnes+1) * DIM_LIGNE
            largeurs = [largCan // nombreColonnes] * nombreColonnes
            for i in range(largCan % nombreColonnes) :
                largeurs[i] += 1
     
            # Mises à jour des dimensions
            ih = 0
            y = DIM_LIGNE
            for ligne in items :
                il = 0
                x = DIM_LIGNE
                for oid in ligne :
                    can.coords(oid, x, y, x+largeurs[il], y+hauteurs[ih])
                    x += largeurs[il] + DIM_LIGNE
                    il += 1
                ih += 1
                try :
                    y += hauteurs[ih] + DIM_LIGNE
                except IndexError :
                    # Dernier tour de boucle
                    break
     
            j=evt.x#//DIM_CASEL)
            i=evt.y#//DIM_CASEL)
            print('Les coordonnées du carreau cliqué sont ('+str(i)+','+str(j)+')')
        else:
            pass
     
    fenetre = tk.Tk()
     
    can = tk.Canvas(
        fenetre,
        width=DIM_CANEVAS[0],
        height=DIM_CANEVAS[1],
        bg='black',
        highlightthickness=0,
    )
    can.grid()
     
    items = []
    colors = ['white', 'yellow']
    y = DIM_LIGNE
     
    for ligne in range(DIM_GRILLE[1]) :
        x = DIM_LIGNE
        ids = []
        colors.reverse()
        for col in range(DIM_GRILLE[0]) :
     
            #text_item = can.create_text(x+DIM_CASEL, y+DIM_CASEL, text="VRAI", fill="white")
     
            if ligne == 0 and col==0:
                text_item = can.create_text(x+DIM_CASEL/2, y+DIM_CASEH/2, text="C/L", fill="black")
                bbox = can.bbox(text_item)
                i = can.create_rectangle(bbox, outline="black", fill="red")
                can.tag_raise(text_item,i)
            elif ligne == 0 and col>0:
                text_item = can.create_text(x+DIM_CASEL/2, y+DIM_CASEH/2, text="YYYY", fill="black")
                bbox = can.bbox(text_item)
                i = can.create_rectangle(bbox, outline="black", fill="red")
                can.tag_raise(text_item,i)
            elif col == 0 and ligne>0:
                text_item = can.create_text(x+DIM_CASEL/2, y+DIM_CASEH/2, text="XXXX", fill="black")
                bbox = can.bbox(text_item)
                i = can.create_rectangle(bbox, outline="black", fill="red")
                can.tag_raise(text_item,i)
            else:
                text_item = can.create_text(x+DIM_CASEL/2, y+DIM_CASEH/2, text="TEXT", fill="black")
                bbox = can.bbox(text_item)
                i = can.create_rectangle(bbox, outline="red", fill=colors[col % 2])
                can.tag_raise(text_item,i)
            ids.append((i,text_item))
            x += DIM_CASEL + DIM_LIGNE
        items.append(ids)
        y += DIM_CASEH + DIM_LIGNE
     
    can.bind('<Button-1>', destroyer)
     
    fenetre.mainloop()

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 736
    Par défaut
    Salut,

    Citation Envoyé par Arsene12 Voir le message
    Pourriez-vous m'aider à le résoudre, svp. Je vous en remercie d'avance.
    Essayez d'énoncer le problème rencontré, bien sûr, histoire qu'on sache quoi regarder dans le code ou qu'on n'en soit pas réduit à lancer le script pour voir ce qui ne va pas, mais pas que: énoncer le problème est le début de la solution.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Par défaut
    Quand j'exécute le script et que je clique sur un label jaune j'obtiens :

    oid = ligne.pop(ic)
    UnboundLocalError: local variable 'ic' referenced before assignment
    J'essaye d'utiliser items[0] car j'ai un tuple, mais ça marche pas.

    Si je mets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for ligne in items[0] :  # au lieu  de in items:
         oid = ligne.pop(ic)
    j'obtiens :

    oid = ligne.pop(ic)
    AttributeError: 'tuple' object has no attribute 'pop'

    Le problème se situe dans cette partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            # Récupération des index ligne et colonne contenant l'id rectangle
            for il, ligne in enumerate(items) :
                if rid in ligne :
                    ic = ligne.index(rid)
                    print(il)
                    break
    Quand je n'ai pas de tuple (ids.append(i)), et que je clique sur un label jaune, print(il) me renvoie un chiffre.
    Mon problème est donc que je n'arrive pas à récupérer les index lignes et colonnes quand j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                text_item = can.create_text(x+DIM_CASEL/2, y+DIM_CASEH/2, text="TEXT", fill="black")
                bbox = can.bbox(text_item)
                i = can.create_rectangle(bbox, outline="red", fill=colors[col % 2])
                can.tag_raise(text_item,i)
            ids.append(i,text_item))

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 736
    Par défaut
    Salut,

    UnboundLocalError: local variable 'ic' referenced before assignment veut juste dire que rien n'a été assigné à 'ic' avant d'y accéder.
    Puis sans réfléchir à cette erreur vous bricolez "for ligne in items[0]" qui récupère un tuple (puisque vous avez fabriqué une liste de listes de tuple) et çà plante avant de rencontrer 'ici' avec: AttributeError: 'tuple' object has no attribute 'pop'.
    Normal, non?
    D'autre part, avant de coder, essayez de réfléchir un peu. Si on affiche un tableau de carrés/rectangles dont on connaît la dimension des côtés, à tout (x, y) on sait retrouver le numéro (i, j) de la case en en divisant x par la longueur d'un côté et y par celui de l'autre côté.... Et c'est bien plus rapide que de parcourir une liste de listes pour comparer les identifiants.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    926
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 926
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    UnboundLocalError: local variable 'ic' referenced before assignment veut juste dire que rien n'a été assigné à 'ic' avant d'y accéder.- W
    C'est bien ce que j'avais déduis dans mon précédent message. Je disais que lorsque j'avais un tuple (ids.append(i,text_item))), print(il) me renvoyait pas de chiffre donc il n'y avait pas d'ic = ligne.index(rid), et ic n'était pas référencé. En bref, la condition rid in ligne n'était pas remplie.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            # Récupération des index ligne et colonne contenant l'id rectangle
            for il, ligne in enumerate(items) :
                if rid in ligne :
                    ic = ligne.index(rid)
                    print(il)
                    break
    Citation Envoyé par wiztricks Voir le message
    D'autre part, avant de coder, essayez de réfléchir un peu. Si on affiche un tableau de carrés/rectangles dont on connaît la dimension des côtés, à tout (x, y) on sait retrouver le numéro (i, j) de la case en en divisant x par la longueur d'un côté et y par celui de l'autre côté.... Et c'est bien plus rapide que de parcourir une liste de listes pour comparer les identifiants.
    - W
    Cette méthode fonctionne bien lorsque je n'ai que des rectangles. Je la maîtrise pas encore entièrement. Je suis en train d'y réfléchir dessus.

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 736
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 736
    Par défaut
    Citation Envoyé par Arsene12 Voir le message
    Je disais que lorsque j'avais un tuple (ids.append(i,text_item))), print(il) me renvoyait pas de chiffre donc il n'y avait pas d'ic = ligne.index(rid), et ic n'était pas référencé. En bref, la condition rid in ligne n'était pas remplie.
    Ben oui: avec ligne, une liste de tuples, et rid, un entier: rid in ligne sera toujours faux. Si vous ne cherchez pas à comprendre ce que vous écrivez...
    Puis soyez attentif: .find_overlapping vous retourne plusieurs items/entiers, vous choisissez le premier de cette liste, pourquoi?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 28/11/2015, 12h25
  2. [Débutant] Supprimer des lignes et des colonnes d'une matrice
    Par hakimetudiant dans le forum MATLAB
    Réponses: 6
    Dernier message: 01/06/2015, 15h24
  3. Supprimer les lignes et les colonnes d'une image
    Par af.zakaria dans le forum OpenCV
    Réponses: 10
    Dernier message: 22/10/2013, 13h55
  4. Réponses: 8
    Dernier message: 29/04/2008, 13h58
  5. Traitement des lignes [suppression des lignes vides]
    Par turbo_chess dans le forum Linux
    Réponses: 4
    Dernier message: 22/03/2007, 09h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo