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 :

Problème temps de latence


Sujet :

Tkinter Python

  1. #1
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut Problème temps de latence
    Bonjour,

    j'ai une grille et quand je clique sur une case de cette grille, ça supprime la ligne et la colonne qui la contiennent.
    Le problème c'est que c'est quasi instantanné pour une grille de 20 X 20 cases, et que ça prend 3 à 4 secondes pour une grille de 50 X 50 cases.
    Pour modifier la taille de la grille dans le code ci-dessous, il suffit de modifier la valeur du paramètre longueurGrille :

    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
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
     
    from tkinter import *
     
    # on crée la fenêtre principale
    fenetre = Tk()
     
    def delete(event,arg1,arg2):
        #print(canvas.grid_slaves(row, column))
        for canvas in fenetre.grid_slaves():
          if int(canvas.grid_info()["row"]) == arg1:
            canvas.grid_forget()
        for canvas in fenetre.grid_slaves():
          if int(canvas.grid_info()["column"]) == arg2:
            canvas.grid_forget() 
     
    longueurGrille=50
    n=1    
    j = 1
    while j < longueurGrille:
        i=1
        while i < longueurGrille:
            canvas = "canvas" + str(i) + str(j)
            canvas = Canvas(fenetre, bg="pale goldenrod")
            canvas.grid(row=j, column=i, sticky=NW+SE)
            if i == 5:
                label = Label(canvas, bg="white", text=n, width=4, height=1, borderwidth=2, relief="solid")
                label.bind("<Button-1>", lambda event, arg1=j, arg2=i: delete(event, arg1, arg2))
            else:
                label = Label(canvas, bg="white", text=n, width=4, height=1, borderwidth=2, relief="solid")
                label.bind("<Button-1>", lambda event, arg1=j, arg2=i: delete(event, arg1, arg2))
            label.grid(row=j, column=i, sticky=NW+SE)        
            i=i+1
            n=n+1
        j=j+1
     
    # on lance la boucle principale
    fenetre.mainloop()
    Pourriez-vous m'aider à résoudre ce problème svp?

    Merci d'avance, cordialement,
    Arsène

  2. #2
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Salut.

    Je n'ai pas autant de latence que toi, mais tu as quand même beaucoup de widgets, 250 canevas, 250 labels avec 250 events

    Je ne sais pas quel est ton but final de faire cela, mais en gérant le tout avec un unique canevas et des rectangles ce serait sans doute mieux, enfin faudrait tester, et voir ce que ça donne niveau perfs, je pense qu'utiliser les tags du rectangle pour y stocker sa ligne et colonne pourrait être intéressant.

    Ah oui en effet, c'est 2500 de chaque, pas 250...
    Le temps ronge l'amour comme l'acide.

  3. #3
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 301
    Points : 6 781
    Points
    6 781
    Par défaut
    Salut,

    Tout d'abord, si on lit bien ton code, tu construis 2500 canvas, pourquoi donc ?

    Ensuite si tu fais un print(canvas.grid_info()["row"]) tu verras que cela te retourne toujours le total de rows, ça ne peut donc pas servir à ce que tu veux faire.

    Et aussi, tu comptes tes lignes et colonnes en commençant par 1, il faut commencer par zéro.

  4. #4
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    Merci de vos réponses.

    si j'ai construit autant de canvas et de labels c'est parce que je voulais avoir une grille avec des cases comportant une inscription à l'intérieur. J'ai supprimé tous les labels et ça n'a pas changé le résultat. Quand y'a 50 canvas et qu'on veut supprimer une ligne ou une colonne, ça demande un certain temps et j'ai besoin d'une réponse immédiate pour que le jeu que je suis en train de faire soit jouable. J'espère qu'avec les rectangle ça sera instantané. Quand j'aurai réglé ce dernier problème, je testerai probablement pygame.

    En tous cas, si je fais un print(canvas.grid_info()["row"]) dans ma fonction delete(),

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def delete(event,arg1,arg2):
        #print(canvas.grid_slaves(row, column))
        for canvas in fenetre.grid_slaves():
          print(int(canvas.grid_info()["row"]))
    j'obtiens bien le rang de chaque canvas et non pas le nombre total de rows à chaque fois. Pour le i et j, je suis d'accord, il faut bien partir de 0.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 778
    Points
    36 778
    Par défaut
    Citation Envoyé par Arsene12 Voir le message
    J'espère qu'avec les rectangle ça sera instantané. Quand j'aurai réglé ce dernier problème, je testerai probablement pygame.
    Avec une complexité en O(n²), il ne faut pas espérer, il faut avoir de bons algos.

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

  6. #6
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Un exemple avec un unique canevas et des rectangles, et en servant des tags pour y enregistrer les index de la ligne et colonne.

    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
    import tkinter as tk
     
    DIM_GRILLE = (50, 50)
    DIM_CASE = 10
    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 delete(evt) :
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        if not r :
            return
        ligne, colonne = can.gettags(r[0])[:2]
        iligne, icolonne = int(ligne[1:]), int(colonne[1:])
     
        for i in range(iligne+1, DIM_GRILLE[1]+1) :
            can.move('l'+str(i), 0, -(DIM_CASE+DIM_LIGNE))
     
        for i in range(icolonne+1, DIM_GRILLE[0]+1) :
            can.move('c'+str(i), -(DIM_CASE+DIM_LIGNE), 0)
     
        can.delete(ligne)
        can.delete(colonne)
     
     
    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>', delete)
     
    fenetre.mainloop()
    C'est déjà bien plus réactif.
    Reste à voir si cela peut te convenir.

    J'ai enregistré les ids des items, à toi aussi de voir si tu en as réellement besoin.
    Le temps ronge l'amour comme l'acide.

  7. #7
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    Merci beaucoup, c'est vraiment top. Je vous félicite. Le code est court et je pouvais rêver mieux. Par contre il va falloir que je m'attelle à bien le comprendre, ligne par ligne. Si j'arrive ensuite à y intégrer mon code, mon objectif sera quasiment atteint.

    Y'aura qu'une dernière chose qui me restera à mettre au point. Ce sera de redimensionner les cases (ou agrandir la taille des lignes et des colonnes) au fil des clics pour que les lignes et les colonnes restantes occupent toujours toute la taille du canvas. J'espère poster le résultat final très bientôt.

  8. #8
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 301
    Points : 6 781
    Points
    6 781
    Par défaut
    Citation Envoyé par Arsene12 Voir le message
    Merci de vos réponses.

    En tous cas, si je fais un print(canvas.grid_info()["row"]) dans ma fonction delete(),

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def delete(event,arg1,arg2):
        #print(canvas.grid_slaves(row, column))
        for canvas in fenetre.grid_slaves():
          print(int(canvas.grid_info()["row"]))
    j'obtiens bien le rang de chaque canvas et non pas le nombre total de rows à chaque fois. Pour le i et j, je suis d'accord, il faut bien partir de 0.
    Heu, j'obtiens toujours le total moi. et tu n'as aucune raison de construire 2500 canvas

  9. #9
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    Citation Envoyé par VinsS Voir le message
    Heu, j'obtiens toujours le total moi.
    Si je place à cet endroit précis le

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print(int(canvas.grid_info()["row"]))
    j'obtiens, à chaque appel de la fonction delete(), par simple clic sur le canvas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    19
    ...
    19
    18
    18
    ...
    18
    17
    17
    ...
    Citation Envoyé par VinsS Voir le message
    et tu n'as aucune raison de construire 2500 canvas
    J'ai abandonné les 2500 canvas. Avec un seul canvas et des rectangles, j'ai plus ce problème de latence. Ce que je cherche à faire maintenant, c'est de redimensionner la largeur des colonnes après qu'il y ait eut suppression d'une colonne. Pour l'instant je n'arrive pas à appliquer la nouvelle largeur que je redéfini pour toutes les colonnes :

    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
    import tkinter as tk
     
    DIM_GRILLE = (10,10)
    #DIM_CASE = 15
    DIM_LIGNE = 1
     
     
    DIM_CASE =[60]
    NBRELignes=[10]
     
     
     
    DIM_CANEVAS = (
        DIM_GRILLE[0]*DIM_CASE[0] + (DIM_GRILLE[0]+1)*DIM_LIGNE,
        DIM_GRILLE[1]*DIM_CASE[0] + (DIM_GRILLE[1]+1)*DIM_LIGNE
    )
     
    def delete(evt) :
     
     
        NBRELignes[0] = NBRELignes[0]-1
        print(DIM_CASE[0])
        DIM_CASE[0]=int(DIM_CANEVAS[0]/NBRELignes[0])    
     
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        print(DIM_CASE[0])
        #print(NBRELignes[0])
        if not r :
            return
        ligne, colonne = can.gettags(r[0])[:2]
        iligne, icolonne = int(ligne[1:]), int(colonne[1:])
     
        #print(iligne)
        #print(icolonne)
     
     
        for i in range(iligne+1, DIM_GRILLE[1]+1) :
            can.move('l'+str(i), 0, -(DIM_CASE[0]+DIM_LIGNE))
     
        for i in range(icolonne+1, DIM_GRILLE[0]+1) :
            can.move('c'+str(i), -(DIM_CASE[0]+DIM_LIGNE), 0)
     
        can.delete(ligne)    
        can.delete(colonne)    
        #myGrid()
        can.forget()
     
    fenetre = tk.Tk()
     
    can = tk.Canvas(fenetre, width=DIM_CANEVAS[0], height=DIM_CANEVAS[1], bg='black', highlightthickness=0,
    )
    can.grid()
     
     
    def myGrid():
     
        items = []
        colors = ['red', 'yellow']
        colors2 = 'green'
        y = DIM_LIGNE
        #print(DIM_GRILLE[0])
     
        for ligne in range(DIM_GRILLE[1]) :
            x = DIM_LIGNE
            ids = []
            colors.reverse()
            for col in range(DIM_GRILLE[0]) :
                #print(DIM_CASE[0])    
                i = can.create_rectangle(
                    x, y, x+DIM_CASE[0], y+DIM_CASE[0],
                    #fill=colors[col%2],
                    fill=colors2,
                    width=0,
                    tags='l{} c{}'.format(ligne, col),
                )
                ids.append(i)
                x += DIM_CASE[0] + DIM_LIGNE
            items.append(ids)
            y += DIM_CASE[0] + DIM_LIGNE
     
        can.bind('<Button-1>', delete)
     
    myGrid()
     
    fenetre.mainloop()

  10. #10
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Salut.

    Citation Envoyé par Arsene12 Voir le message
    Pour l'instant je n'arrive pas à appliquer la nouvelle largeur que je redéfini pour toutes les colonnes
    Sors du contexte de ton application, admettons 12 rangées de case d'une dimension 40, on supprime 1 rangée, comment t'y prendrais-tu pour répartir à peu près équitablement 40 en 11 ?

    Indice, les opérateurs // (reste de la division entière) et % peuvent aider à le faire facilement
    Le temps ronge l'amour comme l'acide.

  11. #11
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    Dans le code de mon dernier post, j'ai choisi 10 rangées et une dimension de case de 60.

    À chaque clic je redéfinis le nouveau nombre de colonnes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    NBRELignes[0] = NBRELignes[0]-1
    et la nouvelle taille des colonnes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DIM_CASE[0]=DIM_CANEVAS[0]//NBRELignes[0]
    Je pense que je vais y arriver. Ce sont les can.move que j'ai pas encore bien compris. Je pensais qu'en les mettant après les can.delete ça aurait marché mais c'est pas le cas.
    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
    def delete(evt) :    
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        if not r :
            return
        ligne, colonne = can.gettags(r[0])[:2]
        iligne, icolonne = int(ligne[1:]), int(colonne[1:])
     
        can.delete(ligne)    
        can.delete(colonne)    
     
        NBRELignes[0] = NBRELignes[0]-1
        print(DIM_CANEVAS[0])
        DIM_CASE[0]=DIM_CANEVAS[0]//NBRELignes[0]    
        print(DIM_CASE[0])
        print(NBRELignes[0])
     
        for i in range(iligne+1, DIM_GRILLE[1]+1) :
            can.move('l'+str(i), 0, -(DIM_CASE[0]+DIM_LIGNE))
     
        for i in range(icolonne+1, DIM_GRILLE[0]+1) :
            can.move('c'+str(i), -(DIM_CASE[0]+DIM_LIGNE), 0)

  12. #12
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    move sert à déplacer un élément du canevas, c'est pas avec cette méthode que tu vas pouvoir redimensionner quelque chose.

    C'est avec la méthode coords qu'il faut le faire
    Le temps ronge l'amour comme l'acide.

  13. #13
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    J'arrive à récupérer les coordonnées du carreau cliqué.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        j=evt.x//60
        i=evt.y//60
        print('Les coordonnées du carreau cliqué sont ('+str(i)+','+str(j)+')')
        print(can.gettags(r[0]))
    Mais pour la méthode coords() je n'ai pas trouvé d'exemples, à part celui-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    blue = w.create_rectangle(5, canvas_height, canvas_width, 2, fill="blue")
    
    To resize, get the coordinates...
    
    x0, y0, x1, y1 = w.coords(blue)
    
    Do some math...
    
    x1 = x0 + b
    
    And reset the coordinates
    
    w.coords(blue, x0, y0, x1, y1)
    Je vais continuer de chercher.

  14. #14
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    Ça devrait théoriquement ressembler à quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        for i in range(iligne+1, DIM_GRILLE[1]) :
            #can.move('l'+str(i), 0, -(DIM_CASE[0]+DIM_LIGNE))
            can.coords('l'+str(i),i, DIM_LIGNE,DIM_CASE[0],DIM_CASE[0]) 
        for i in range(icolonne+1, DIM_GRILLE[0]) :
            #can.move('c'+str(i), -(DIM_CASE[0]+DIM_LIGNE), 0)
            can.coords('c'+str(i),DIM_LIGNE,i,DIM_CASE[0],DIM_CASE[0])
    ou
     for i in range(iligne+1, DIM_GRILLE[1]) :
            can.coords('l'+str(i), height=DIM_CASE[0], width=DIM_CASE[0]) 
        for i in range(icolonne+1, DIM_GRILLE[0]) :
            can.coords('c'+str(i), height=DIM_CASE[0], width=DIM_CASE[0])

  15. #15
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Tu devrais oublier les tags et plutôt agir et travailler sur le tableau des items enregistrés.
    Le temps ronge l'amour comme l'acide.

  16. #16
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    La première des choses que je dois savoir faire, c'est redimensionner un simple rectangle :

    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
    import tkinter as tk
    from tkinter import *
     
    root = tk.Tk()
     
    def modifTaille(evt):
        canvas.coords(rect_item,1,1,50,50)   
     
    canvas = Canvas(root, bg="pale goldenrod")
    canvas.grid(row=1, column=1, sticky=NW+SE)
     
    rect_item = canvas.create_rectangle(1,1,100,100, outline="red", fill="black")
     
    canvas.bind('<Button-1>', modifTaille)
     
    root.mainloop()
    Je viens de trouver la formule. Il faut que j'utilise le nom de l'item. Si je tape dans la fonction delete(evt) :

    can.coords(items[0][0],1,1,50,50)

    la première case est bien redimensionnée. Il faut maintenant que je trouve comment faire pour redimensionner toutes les cases. J'y suis presque.

  17. #17
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    Je pensais tenir presque la solution mais ça se complique. Quand je tape les 2 lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        can.coords(items[0][0],1,1,50,50)
        can.coords(items[2][0],1,1,50,50)
    la première case adopte bien les nouvelles dimensions mais la deuxième est carrément supprimée.

    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
    import tkinter as tk
     
    DIM_GRILLE = (10, 10)
    #DIM_CASE = 15
    DIM_LIGNE = 1
    DIM_CASE =[60]
    NBRELignes=[10]
     
    DIM_CANEVAS = (
        DIM_GRILLE[0]*DIM_CASE[0] + (DIM_GRILLE[0])*DIM_LIGNE,
        DIM_GRILLE[1]*DIM_CASE[0] + (DIM_GRILLE[1])*DIM_LIGNE
    )
     
    def delete(evt) :    
     
        NBRELignes[0] = NBRELignes[0]-1
        #print(DIM_CANEVAS[0])
        #DIM_CASE[0]=DIM_CANEVAS[0]//NBRELignes[0]
        print(DIM_CASE[0])
        #print(NBRELignes[0])
     
        r = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
        if not r :
            return
        ligne, colonne = can.gettags(r[0])[:2]
        iligne, icolonne = int(ligne[1:]), int(colonne[1:])
     
        j=evt.x//60
        i=evt.y//60
     
     
        print(items[0][0])
        can.coords(items[0][0],1,1,50,50)
        can.coords(items[2][0],1,1,50,50)
     
     
    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']
    colors2 = 'green'
     
    #print(DIM_GRILLE[0])
     
    def myGrid(arg=DIM_CASE[0]):
     
        y = DIM_LIGNE
     
        for ligne in range(DIM_GRILLE[1]) :
            x = DIM_LIGNE
            ids = []
            colors.reverse()
            for col in range(DIM_GRILLE[0]) :
                #print(DIM_CASE[0])
                #print(str(col)+str(ligne))
                i = can.create_rectangle(
                    x, y, x+DIM_CASE[0], y+DIM_CASE[0],
                    #fill=colors[col%2],
                    fill=colors2,
                    width=0,
                    tags='l{} c{}'.format(ligne, col),
                )
                ids.append(i)
                x += DIM_CASE[0] + DIM_LIGNE
            items.append(ids)
            y += DIM_CASE[0] + DIM_LIGNE
     
    can.bind('<Button-1>', delete)
     
    myGrid()
     
    fenetre.mainloop()

  18. #18
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Salut.

    Je t'avais dit de laisser tomber les tags car ça va te compliquer la tâche plutôt qu'autre chose.

    Il faut procéder par étapes et avec une certaine logique, et quand on arrive pas à se représenter quelque chose visuellement dans notre code, on prend une feuille et un crayon et on réfléchit dessus.

    On arrive à aboutir à quelque chose de simple comme :
    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 delete(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>', delete)
     
    fenetre.mainloop()
    Et bien évidemment, on peut améliorer ça au fur et à mesure de la relecture du code, en utilisant par exemple d'autres fonctions pour clarifier tout ça, pour la répartition des dimensions des lignes et colonnes, suppressions des items, redimensionnements, etc.
    Regarder aussi, si on ne peut pas faire directement certaines choses en une fois, etc.
    Le temps ronge l'amour comme l'acide.

  19. #19
    Membre actif
    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
    Points : 273
    Points
    273
    Par défaut
    C'est un code pas évident à comprendre de premier abord car il témoigne d'une excellente maîtrise technique. Il mériterait d'être 3 fois plus commenté pour qu'un débutant comme moi puisse en saisir toute la logique. En tout cas, j'espère qu'il me paraitra plus clair lorsque j'aurai plus de pratique. Je pense que je vais pouvoir l'exploiter et qu'il me permettra de progresser. Je vous remercie vraiment beaucoup pour cette aide précieuse.

  20. #20
    Membre confirmé

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Points : 503
    Points
    503
    Billets dans le blog
    1
    Par défaut
    Salut !

    Citation Envoyé par Arsene12 Voir le message
    ... car il témoigne d'une excellente maîtrise technique.
    C'est gentil, mais moi je ne maîtrise rien

    Citation Envoyé par Arsene12 Voir le message
    Il mériterait d'être 3 fois plus commenté pour qu'un débutant comme moi puisse en saisir toute la logique.
    Si ça ne tient quà ça :

    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
    def delete(evt) :
        # On récupère dans le canevas tous les items contenant le point x et y
        # du clic, attention au cas où tu ajouterais d'autres items sur le canevas
        # car ils pourraient se retrouver dans cette liste, donc s'assurer de les
        # mettre en state disabled, ou alors utiliser tag_bind plutôt que bind
        # avec un tag associé aux rectangles.
        listeItems = can.find_overlapping(evt.x, evt.y, evt.x, evt.y)
     
        # S'il n'y a pas d'items dans la liste, on ne fait rien.
        if not listeItems :
            return
     
        # On utilise le 1er item de la liste.
        rectangleId = listeItems[0]
     
        # Récupération des index ligne et colonne contenant l'id rectangle
        # dans notre tableau items.
     
        # Parcours du tableau des items de nos rectangles pour tenter de récupérer
        # dans le tableau la ligne et colonne où se situe le rectangleId.
        for indexLigne, ligne in enumerate(items) :
            # Si l'identifiant du rectangle se situe dans cette ligne.
            if rectangleId in ligne :
                # On récupère son index à l'aide de la méthode index de list.
                indexColonne = ligne.index(rectangleId)
                # On interrompt la boucle car on a obtenu ce qu'on cherchait.
                break
        else :
            # Par sécurité supplémentaire on ne fait rien si on n'a pas obtenu
            # l'index de la colonne dans le tableau items.
            # Voir comment s'utilise la boucle for ... else.
            return
     
        # Suppressions de la ligne et colonne du tableau items
        # Et suppression dans le canevas
     
        # On récupère les ids des rectangles de la ligne des items que l'on enlève
        # de la liste items à l'aide de la méthode list.pop.
        listeRectangleIds = items.pop(indexLigne)
        # Pour chaque identifiant de rectangle de la ligne on le supprime du canevas.
        for oid in listeRectangleIds :
            can.delete(oid)
     
        # On parcourt à nouveau la liste d'items pour cette fois, supprimer dans
        # chaque ligne l'index indexColonne et en même temps le supprimer du canevas.
        for ligne in items :
            # Suppression et récupération à l'aide de list.pop l'identifiant du
            # rectangle à supprimer.
            oid = ligne.pop(indexColonne)
            # Suppression sur le canevas.
            can.delete(oid)
     
        # On regarde à l'aide d'any si toutes les lignes (list) sont vides, le cas
        # échéant on ne fait plus rien de ce qui suivra car il n'y a plus rien à
        # redimensionner.
        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 rectangles.
     
        # hauteurs de chaque rectangle d'une colonne.
     
        # On déduit de la hauteur du canevas le total en pixel des largeurs des
        # lignes pour obtenir la hauteur réelle à répartir.
        hautCan = DIM_CANEVAS[1] - (nombreLignes+1) * DIM_LIGNE
        # Répartition de la hauteur de chaque ligne
        hauteurs = [hautCan // nombreLignes] * nombreLignes
        # On y ajoute ce qu'il reste car sinon, on aura une zone non remplie sur le
        # bas (pour les hauteurs) et la droite (pour les largeurs) du canevas.
        # 300 == 300 // 8 * 8 + 300 % 8 => voir fonction divmod
        for i in range(hautCan % nombreLignes) :
            hauteurs[i] += 1
     
        # Même chose que précédement mais cette fois pour les largeurs.
        # Calculs des dimensions de chaque colonnes
     
        # largeurs de chaque rectangle d'une ligne.
        largCan = DIM_CANEVAS[0] - (nombreColonnes+1) * DIM_LIGNE
        largeurs = [largCan // nombreColonnes] * nombreColonnes
        for i in range(largCan % nombreColonnes) :
            largeurs[i] += 1
     
        # On a désormais les dimensions que chaque rectangle doit avoir en fonction
        # de la ligne et de la colonne où ils se situent.
     
        # Initialisation de l'index indexHauteur à 0
        indexHauteur = 0
        y = DIM_LIGNE
        for ligne in items :
            # Initialisation de l'index indexLargeur à 0 à chaque ligne parcourue
            indexLargeur = 0
            # Initialisation de la coordonnée x à chaque ligne parcourue
            x = DIM_LIGNE
            # Pour chaque identifiant rectangle, on définit ses nouvelles coordonnées
            # à l'aide de la méthode coords de tkinter.Canvas.
            for oid in ligne :
                can.coords(oid, x, y, x+largeurs[indexLargeur], y+hauteurs[indexHauteur])
                # On incrémente le x de cette largeur + la largeur d'une ligne.
                x += largeurs[indexLargeur] + DIM_LIGNE
                # on incrémente l'index largeur après chaque rectangle replacés.
                indexLargeur += 1
            # on incrémente l'index hauteur après chaque ligne parcourue
            indexHauteur += 1
     
            try :
                y += hauteurs[indexHauteur] + DIM_LIGNE
            except IndexError :
                # Ici cela ne se produira que lors du dernier tour de boucle, car
                # indexHauteur sera supérieur à l'index max de la liste hauteurs.
                break
    Bon, là y'a trop de commentaires, et s'il y'en a pas assez, je sais pas quoi ajouter de plus.
    Après tu peux faire des prints à foisons pour visualiser ce que contiennent les variables de cette fonction.
    Mais ce code n'est pas bien compliqué, c'est uniquement un travail sur un tableau.
    Le temps ronge l'amour comme l'acide.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Interbase 7] Problème temps d'exécution
    Par ch0upette dans le forum InterBase
    Réponses: 9
    Dernier message: 20/02/2007, 23h31
  2. Mesure de temps de latence d'un LCD
    Par Txitxounet dans le forum Bibliothèques
    Réponses: 3
    Dernier message: 08/11/2006, 22h06
  3. Problème de temps de latence avec KeyAdapter
    Par marissa_mean dans le forum AWT/Swing
    Réponses: 16
    Dernier message: 08/10/2006, 20h35
  4. [MySQL] Problème temps d'éxécution trop long
    Par Yo. dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 13/06/2006, 14h55
  5. [KeyPressed] temps de latence
    Par dieurouille dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 06/06/2006, 21h01

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