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

Résolu/Fermé
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022 - 2 mars 2022 à 07:06
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022 - 4 mars 2022 à 23:54
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

mamiemando Messages postés 33433 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 décembre 2024 7 809
Modifié le 2 mars 2022 à 16:09
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
jee pee Messages postés 40559 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 17 décembre 2024 9 459
Modifié le 3 mars 2022 à 10:45
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
yg_be Messages postés 23399 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 17 décembre 2024 Ambassadeur 1 556
2 mars 2022 à 12:25
bonjour, le code fonctionne bien?
0
jee pee Messages postés 40559 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 17 décembre 2024 9 459
Modifié le 2 mars 2022 à 13:34
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

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

Posez votre question
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022
Modifié le 4 mars 2022 à 12:45
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
jee pee Messages postés 40559 Date d'inscription mercredi 2 mai 2007 Statut Modérateur Dernière intervention 17 décembre 2024 9 459
Modifié le 2 mars 2022 à 18:12
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
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022
2 mars 2022 à 17:35
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
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022
Modifié le 4 mars 2022 à 12:46
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
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022
Modifié le 4 mars 2022 à 12:47
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
mamiemando Messages postés 33433 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 17 décembre 2024 7 809
Modifié le 4 mars 2022 à 14:15
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
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022
Modifié le 4 mars 2022 à 12:47
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
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022
4 mars 2022 à 21:32
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
billyV33 Messages postés 23 Date d'inscription dimanche 10 février 2019 Statut Membre Dernière intervention 9 mars 2022
4 mars 2022 à 23:54
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