Petite matrice répétée n fois et afficher avec Tkinter

Résolu
billyV33 Messages postés 24 Statut Membre -  
billyV33 Messages postés 24 Statut Membre -
Bonjour,
J'ai une petite matrice 5x5 qui forme une grille de base. Je voudrait afficher la même petite grille n fois pour remplir le canvas redimensionné.
Mon premier code en Python! Je lis et lis sur le net pour avoir un indice mais rien! Je ne débloque pas.
Ici un morceau du code. Merci beaucoup pour votre aide!

from tkinter import Canvas, ALL

import numpy as np
import tkinter as tk

fen1 = tk.Tk()
fen1.geometry("900x600")

SIZE = 80
c = 5
height = SIZE * c
width = SIZE * c

# matrice 5x5 du départ
matrice = [[1, -2, 1, -1, -1], [1, -2, 1, -2, -2], [1, 1, -2, 2, -2], [1, 1, -1, 2, 2], [2, 2, 2, 2, -1]]

can1 = Canvas(fen1, width=width, height=height)
can1.place(x=20, y=20)

twod_list = []
for i in range(0, 20):
    for j in range(0, 20):
        twod_list.append(matrice)

matrice = np.copy(twod_list)

can1.delete(ALL)
can1.config(width=400, height=400, bg='white', borderwidth=0, highlightthickness=0)

t = 0
z = 5
while t !=  width / c: # t=X
    u = 0
    while u != z:
        x = t
        y = u
        print("y=", y, "u=", u)
        print(matrice[x][x, y])
        if (matrice[x][x, y]) == -1:
            can1.create_rectangle(x * c, y * c, x * c + c, y * c + c, fill='black')
        elif (matrice[x][x, y]) == 1:
            can1.create_rectangle(x * c, y * c, x * c + c, y * c + c, fill='dark blue')
        elif (matrice[x][x, y]) == 2:
            can1.create_oval(x * c, y * c, x * c + c, y * c + c, fill='dark red')
        else:
            can1.create_oval(x * c, y * c, x * c + c, y * c + c, fill='purple')
        u += 1
    t += 1

fen1.mainloop()



Configuration: Linux / Firefox 91.0

11 réponses

  1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 942
     
    Bonjour,

    Si j'ai bien compris ce que tu veux faire et que tu es prêt à utiliser
    numpy
    , tu peux utiliser
    np.tile
    :

    Exemple :

    m = [[10, 20], [30, 40]]
    big_m = np.tile(m, (2, 3)) # 2 répétitions verticalement, 3 répétitions horizontalement
    print(big_m)


    ... renvoie :

    array([[10, 20, 10, 20, 10, 20],
    [30, 40, 30, 40, 30, 40],
    [10, 20, 10, 20, 10, 20],
    [30, 40, 30, 40, 30, 40]])


    Bonne chance
    1
  2. jee pee Messages postés 9441 Date d'inscription   Statut Modérateur Dernière intervention   9 981
     
    Attention avec une matrice carrée 5X5 on ne distingue pas ce qui est ligne et colonne, à l'affichage cela a de l'importance car naturellement on (moi en tout cas) va bâtir un tableau lignes x colonnes mais tk travaille en colonnes x lignes.

    J'ai fait le code avec une matrice dupliquée n fois, sans np, cela donne un adressage compliqué à 4 niveaux matriceM[v][w][x][y]

    from tkinter import Canvas, ALL
    
    import numpy as np
    import tkinter as tk
    
    # matrice 6lignes x 5colonnes
    matrice = [[1, -2, 1, -1, -1], [1, -2, 1, -2, -2], [1, 1, -2, 2, -2], [1, 1, -1, 2, 2], [2, 2, 2, 2, -1], [-2, -2, -2, -2, -2]]
    nbLig = len(matrice)    # nombre de lignes
    nbCol = len(matrice[0]) # nombre de colonnes
    
    multiplier = 3 # nombre de fois à afficher la matrice
    taille = 20    # taille d'un point
    hauteur = taille * multiplier * nbLig
    largeur = taille * multiplier * nbCol
    
    matriceM = [[[[matrice[i][j] for i in range(nbLig)] for j in range(nbCol)] for k in range(multiplier)] for l in range(multiplier)]
    # C = [[0]*m for i in range(n)] # matrice initialisée à zéro
    
    fen1 = tk.Tk()
    fen1.geometry("{}x{}".format(largeur+40,hauteur+40))
    
    can1 = Canvas(fen1, width=largeur, height=hauteur)
    can1.place(x=20, y=20)
    
    can1.delete(ALL)
    can1.config(width=largeur, height=hauteur, bg='white', borderwidth=0, highlightthickness=0)
    
    for v in range(multiplier):
       for w in range(multiplier):
          for x in range(nbCol):
             for y in range(nbLig):
    #            print(v,w,x,y,matriceM[v][w][x][y])
                if (matriceM[v][w][x][y]) == -1:
                    can1.create_rectangle(v * nbCol * taille + (x * taille), w * nbLig * taille + (y * taille), v * nbCol * taille + ((x +1) * taille), w * nbLig * taille + ((y+1) * taille), fill='black')
                elif (matriceM[v][w][x][y]) == 1:
                    can1.create_rectangle(v * nbCol * taille + (x * taille), w * nbLig * taille + (y * taille), v * nbCol * taille + ((x +1) * taille), w * nbLig * taille + ((y+1) * taille), fill='dark blue')
                elif (matriceM[v][w][x][y]) == 2:
                   can1.create_oval(v * nbCol * taille + (x * taille), w * nbLig * taille + (y * taille), v * nbCol * taille + ((x +1) * taille), w * nbLig * taille + ((y+1) * taille), fill='dark red')
                else:
                   can1.create_oval(v * nbCol * taille + (x * taille), w * nbLig * taille + (y * taille), v * nbCol * taille + ((x +1) * taille), w * nbLig * taille + ((y+1) * taille), fill='purple')
    
    fen1.mainloop()


    et un autre avec np suivant l'exemple de mamiemando :
    from tkinter import Canvas, ALL
    
    import numpy as np
    import tkinter as tk
    
    # matrice 6lignes x 5colonnes
    matrice = [[1, -2, 1, -1, -1], [1, -2, 1, -2, -2], [1, 1, -2, 2, -2], [1, 1, -1, 2, 2], [2, 2, 2, 2, -1], [-2, -2, -2, -2, -2]]
    nbLig = len(matrice)    # nombre de lignes
    nbCol = len(matrice[0]) # nombre de colonnes
    
    multiplier = 3 # nombre de fois à afficher la matrice
    taille = 20    # taille d'un point
    hauteur = taille * multiplier * nbLig
    largeur = taille * multiplier * nbCol
    
    matriceM = np.tile(np.array(matrice), (multiplier, multiplier))
    
    fen1 = tk.Tk()
    fen1.geometry("{}x{}".format(largeur+40,hauteur+40))
    
    can1 = Canvas(fen1, width=largeur, height=hauteur)
    can1.place(x=20, y=20)
    
    can1.delete(ALL)
    can1.config(width=largeur, height=hauteur, bg='white', borderwidth=0, highlightthickness=0)
    
    for x in range(len(matriceM)):
       for y in range(len(matriceM[0])):
    #      print(x,y,matriceM[x][y])
          if (matriceM[x][y]) == -1:
             can1.create_rectangle(y * taille, x * taille, (y +1) * taille, (x+1) * taille, fill='black')
          elif (matriceM[x][y]) == 1:
             can1.create_rectangle(y * taille, x * taille, (y +1) * taille, (x+1) * taille, fill='dark blue')
          elif (matriceM[x][y]) == 2:
             can1.create_oval(y * taille, x * taille, (y +1) * taille, (x+1) * taille, fill='dark red')
          else:
             can1.create_oval(y * taille, x * taille, (y +1) * taille, (x+1) * taille, fill='purple')
    
    fen1.mainloop()


    1
  3. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 588
     
    bonjour, le code fonctionne bien?
    0
  4. jee pee Messages postés 9441 Date d'inscription   Statut Modérateur Dernière intervention   9 981
     
    Bonjour,

    Dans le cas présent tu ne devrais pas utiliser des while, cela t'oblige à incrémenter le compteur, et manifestement tu le gères mal puisque tu arrives à un indice (5) alors que ta matrice avec 5 valeurs va de (0) à (4). Puis tu as trop de variables x = t, y = u, prends x et y dès le départ. Pour remplacer while une boucle for gère seule l'indice.

    Après tu as une matrice originelle que tu veux dupliquer 20 fois, mais au final tu n'as pas 20,20,5,5 mais 400,5,5

    D'ailleurs si l'objectif c'est d'afficher n fois la matrice originelle, il n'y a pas besoin de créer cette nouvelle matrice. Tu peux avec une boucle dupliquer la matrice originelle.

    Tu devrais commencer par afficher une fois la matrice pour avoir ton programme qui fonctionne. Donc
    for x in range(5):
       for y in range(5):


    et une fois que c'est bon, tu rajoutes 2 boucles pour dupliquer le résultat n fois :
    for v in range(n):
       for w in range(n):
          for x in range(5):
             for y in range(5):


    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. billyV33 Messages postés 24 Statut Membre
     
    Bonjour!

    Merci beaucoup pour vos réponses aussi rapides!
    J'ai essayé avec les
    for
    et le problème que je n'arrive pas à régler et qu'on dirait que l'image reste toujours à la même place. Je ne sais pas si c'est le choix au niveau du
    twod_liste
    qui est mon erreur. est-ce qu'il me traduit dans un mauvais format pour une lecture linéaire? voici mon code avec les for J'ai mis quelques
    print()
    :-)
    from tkinter import Canvas, ALL
    import numpy as np
    import tkinter as tk
    
    fen1 = tk.Tk()
    fen1.geometry("900x600")
    
    SIZE = 80
    c = 5
    height = SIZE * c
    width = SIZE * c
    # matrice 5x5
    matrice = [[1, -2, 1, -1, -1], [1, -2, 1, -2, -2], [1, 1, -2, 2, -2], [1, 1, -1, 2, 2], [2, 2, 2, 2, -1]]
    
    can1 = Canvas(fen1, width=width, height=height)
    can1.place(x=20, y=20)
    
    twod_list = []
    for i in range(0, 20):
        for j in range(0, 20):
            twod_list.append(matrice)
    
    matrice = np.copy(twod_list)
    
    can1.delete(ALL)
    can1.config(width=400, height=400, bg='white', borderwidth=0, highlightthickness=0)
    
    v = 0
    w = 0
    x = 0
    y = 0
    n = 20
    z = 5
    for v in range(n):
        print("v", v, "n", n)
        for w in range(n):
            print("w", w, "n", n)
            for x in range(z):
                print("x", x, "z", z)
                for y in range(z):
                    print("--------y", y, "x", x)
                    if (matrice[x][x, y]) == -1:
                        can1.create_rectangle(x * c, y * c, x * c + c, y * c + c, fill='black')
                    elif (matrice[x][x, y]) == 1:
                        can1.create_rectangle(x * c, y * c, x * c + c, y * c + c, fill='dark blue')
                    elif (matrice[x][x, y]) == 2:
                        can1.create_oval(x * c, y * c, x * c + c, y * c + c, fill='dark red')
                    else:
                        can1.create_oval(x * c, y * c, x * c + c, y * c + c, fill='purple')
    
    
    fen1.mainloop()
    #
    #    line 43, in <module>
    #    if matrice[x][y] == -1:
    # ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
    # if (matrice[x][x, y]) == -1:
    # matrice = np.copy(twod_list)
    
    0
    1. jee pee Messages postés 9441 Date d'inscription   Statut Modérateur Dernière intervention   9 981
       
      ton soucis doit donc se situer dans les coordonnées que tu donnes (pixel debut h, pixel debut l, pixel fin h, pixel fin l) tu ne prends pas en compte v et w qui sont chargés de déplacer le motif de la matrice

      avec un for, pas besoin d'initialiser l'indice avant , j'ai écrit ce code

      from tkinter import Canvas, ALL
      
      import numpy as np
      import tkinter as tk
      
      fen1 = tk.Tk()
      fen1.geometry("900x600")
      
      # matrice 5x5 du départ
      matrice = [[1, -2, 1, -1, -1], [1, -2, 1, -2, -2], [1, 1, -2, 2, -2], [1, 1, -1, 2, 2], [2, 2, 2, 2, -1]]
      
      multiplier = 4 # nombre de fois à afficher la matrice
      taille = 30 # taille d'un point
      hauteur = taille * multiplier * len(matrice)
      largeur = taille * multiplier * len(matrice)
      
      can1 = Canvas(fen1, width=largeur, height=hauteur)
      can1.place(x=20, y=20)
      
      can1.delete(ALL)
      can1.config(width=largeur, height=hauteur, bg='white', borderwidth=0, highlightthickness=0)
      
      for v in range(multiplier):
         for w in range(multiplier):
            for x in range(len(matrice)):
               for y in range(len(matrice)):
                  print(v,w,x,y,matrice[x][y])
                  if (matrice[x][y]) == -1:
                      can1.create_rectangle(v * len(matrice) * taille + (x * taille), w * len(matrice) * taille + (y * taille), v * len(matrice) * taille + ((x +1) * taille), w * len(matrice) * taille + ((y+1) * taille), fill='black')
                  elif (matrice[x][y]) == 1:
                      can1.create_rectangle(v * len(matrice) * taille + (x * taille), w * len(matrice) * taille + (y * taille), v * len(matrice) * taille + ((x +1) * taille), w * len(matrice) * taille + ((y+1) * taille), fill='dark blue')
                  elif (matrice[x][y]) == 2:
                     can1.create_oval(v * len(matrice) * taille + (x * taille), w * len(matrice) * taille + (y * taille), v * len(matrice) * taille + ((x +1) * taille), w * len(matrice) * taille + ((y+1) * taille), fill='dark red')
                  else:
                     can1.create_oval(v * len(matrice) * taille + (x * taille), w * len(matrice) * taille + (y * taille), v * len(matrice) * taille + ((x +1) * taille), w * len(matrice) * taille + ((y+1) * taille), fill='purple')
      
      fen1.mainloop()
      0
  7. billyV33 Messages postés 24 Statut Membre
     
    Pour le np.tile j'avais vu ça et je me disais que c'était ce que je cherchais mais je n'avais pas compris le principe.
    je vais mieux regarder pour comprendre merci beaucoup!
    Parce que je veux répéter le même motif plusieurs fois pour remplir le canvas
    je vous reviens
    0
  8. billyV33 Messages postés 24 Statut Membre
     
    Petit essai avec
    np.tile
    mais je ne dois pas bien l'utiliser parce que je ne réussis pas à changer le nombre de répétitions à la ligne 19 Par contre je vois apparaître la grille 4 fois et la même!!!

    Merci !

    from tkinter import Canvas, ALL
    import numpy as np
    import tkinter as tk
    
    fen1 = tk.Tk()
    fen1.geometry("900x600")
    
    SIZE = 80
    c = 5
    height = SIZE * c
    width = SIZE * c
    # matrice 5x5
    matrice = [[1, -2, 1, -1, -1], [1, -2, 1, -2, -2], [1, 1, -2, 2, -2], [1, 1, -1, 2, 2], [2, 2, 2, 2, -1]]
    print("\nlong mat orig", len(matrice))
    can1 = Canvas(fen1, width=width, height=height)
    can1.place(x=20, y=20)
    
    b = np.array(matrice)
    matrice = np.tile(b, (5, 1))
    print("\nlong mat", len(matrice))
    can1.delete(ALL)
    can1.config(width=400, height=400, bg='white', borderwidth=0, highlightthickness=0)
    
    x = 0
    y = 0
    z = 20
    for x in range(z):
        print("x", x, "z", z)
        for y in range(5):
            print("--------y", y, "x", x)
            if matrice[x][y] == -1:
                can1.create_rectangle(x * c, y * c, x * c + c, y * c + c, fill='blue')
            elif matrice[x][y] == 1:
                can1.create_rectangle(x * c, y * c, x * c + c, y * c + c, fill='green')
            elif matrice[x][y] == 2:
                can1.create_oval(x * c, y * c, x * c + c, y * c + c, fill='red')
            else:
                can1.create_oval(x * c, y * c, x * c + c, y * c + c, fill='yellow')
    
    fen1.mainloop()
    0
  9. billyV33 Messages postés 24 Statut Membre
     
    En mettant :
    z = len(matrice)
    c'est logique. Il me reste à trouver comment augmenter le nombre de tile et
    matrice = numpy.tile(b, (20, 5))
    me donne la première ligne du canvas en entier avec la répétition de la grille.

    Je continue, merci !
    0
    1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 942
       
      Le tuple passé en paramètre indique le nombre de répétitions verticales et horizontales. Je te renvoie à mon message #3 et et au message # 10 de jee pee et si ça n'est pas clair, dis-moi ce que tu ne comprends pas où n'arrive pas à faire sur un exemple minimal (comme celui de mon message #3).

      Bonne chance
      0
  10. billyV33 Messages postés 24 Statut Membre
     
    Je viens de voir ! Ça fonctionne avec l'exemple des for ! MERCI !
    Même en diminuant la grosseur des cases rondes ou carrées!
    multiplier = 20  # nombre de fois à afficher la matrice
    taille = 5  # taille d'un point

    Merci beaucoup !
    0
  11. billyV33 Messages postés 24 Statut Membre
     
    Me revoilà! mon problème est l'affichage, mais surtout j'ai besoin de trouver la matrice modifiée en plus de l'affichage
    avec les tiles je vois bien que la matrice augmente mais ça m'affiche juste une colonne ou juste une ligne plaine de grille répétée
    je fais des tests mais pas encore trouvé
    merci beaucoup
    0
  12. billyV33 Messages postés 24 Statut Membre
     
    Merci infiniment! J'ai trouvé!!!
    Un petit mélange de vos deux suggestions!
    Mon code est bien plus long et il y a des appels à d'autre fonctions mais en gros le morceau de code que je vous ai présenté représenté assez bien mon problème
    Donc, j'ai utilisé le TIle pour redimensionner la matrice et le for pour l'affichage au bon endroit et j'ai du bien vérifier de ne pas faire un delete une fois de trop le canvas et aussi m'assurer que mes boutons fonctionnent toujours aussi bien!
    Il va me rester un petit détail mais je devrais y arrivé
    Merci encore pour votre précieux aide! Bonne journée! Résolu!

           
    # CANVAS longueur matrice 5
    can1.delete(ALL)

    hauteur = c * 16 * len(matrice)
    largeur = c * 16 * len(matrice)
    can1.delete(ALL)
    can1.config(width=largeur, height=hauteur, bg='black', borderwidth=0, highlightthickness=0)

    # TILE tuile
    matrice = np.tile(matrice, (40, 40))
    matrice = np.array(matrice)

    print("\nlong mat", len(matrice), "\n", matrice)
    # ...suite dans une fn pour les for :)

    0