Placement widget tkinter

Bonjour, je voudrais placer 20 Canvas rectangle dans mon programme en les plaçant par 5 sur une ligne, Je n'arrive pas a placer correctement les widgets au bon endroit surtout pour placer les 5 widgets sur la deuxième ranger. le rectangle de la deuxième rangée et collé avec la première.

voici mon programme:

from tkinter import *


f = Tk()
f.title("SAMARITAIN")
f.geometry("700x700")

can = Canvas(width= 550, height =600, bg ="green")
can.pack()
can.create_rectangle(10,50,91,91, fill='white')
can.create_rectangle(111,50,186,91,fill='white')
can.create_rectangle(205,50,285,91,fill='white')
can.create_rectangle(303,50,390,91,fill='white')
can.create_rectangle(410,50,500,91,fill='white')
can.create_rectangle(10,101,114,91)
f.mainloop()

pourriez-vous m'aider à résoudre ce problème svp.
Windows / Chrome 103.0.0.0

3 réponses

  1. Contributeur

    bonjour,

    et ainsi pour le 2ième?

    can.create_rectangle(10,100,91,141)
    1. Bonjour,

      au lieu d'écrire 20 fois can.create_rectangle(), pourquoi ne ferais-tu pas 2 boucles imbriquées

      la 1ere de 0 à 4 pour les lignes, la 2eme de 0 à 5 pour les colonnes

      et dans la boucle, tu calcules les coordonnées du rectangle en fonction des x et y de départ (10,50)

      de la distance entre 2 rectangles et de la hauteur et largeur d'un rectangle

      for lignes in range(4):
          for colonnes in range(5):
              #ici : calcul de x et y
              can.create_rectangle(x, y, x+largeur, y+hauteur, fill='white')
      
          #ici : y de départ =  y de départ + distance en hauteur dessiner pour la ligne suivante
      
      1. Contributeur
        x1,y1=40,50
        r1,r2=80,40
        d1,d2=20,40
        for j in range(4):
            for i in range(5):
                x,y=x1+i*(r1+d1),y1+j*(r2+d2)
                can.create_rectangle(x,y,x+r1,y+r2, fill='white')
      2. @yg_be

        Bonsoir yb_be, ton code fonctionne parfaitement, pourrais tu m'expliquer en détail le mécanisme de ton code s'il te plait car je n'y comprend rien surtout les variables(coordonnées du widgets) .

         Je souhaite ajouter des étiquettes (numéros) au dessus de chaque widgets et je voudrais également  écrire a l'intérieur  avec la fonction create_text() des nombres flottants mais je ne suis pas encore doué pour déterminé les coordonnées de chaque variables.

        Merci.

      3. Contributeur
        @maxime_boris

        J'ai ajouté des commentaires, et un print().  Examine le résultat du print().

        from tkinter import *
        f = Tk()
        f.title("SAMARITAIN")
        f.geometry("700x700")
        can = Canvas(width= 550, height =600, bg ="green")
        can.pack()
        x1,y1=40,50   # position du premier rectangle
        r1,r2=80,40   # dimension des rectangles
        d1,d2=20,40   # espaces horizontal et vertical entre deux rectangles
        for j in range(4):
            for i in range(5):
                x,y=x1+i*(r1+d1),y1+j*(r2+d2)
                print("Position du rectangle en ligne {}, colonne {}:{}".format(i+1,j+1,(x,y)))
                can.create_rectangle(x,y,x+r1,y+r2, fill='white')
        f.mainloop()
        
    2. Bonjour, en ajoutant les étiquettes à tes rectangles.

      import tkinter as tk
      import random
      
      RECT_WIDTH, RECT_HEIGHT = 80, 95
      START_X, START_Y = 40, 50
      MARGIN_HORIZONTAL, MARGIN_VERTICAL = 20, 40
      
      # Création de nombres au hasard afin d'avoir du contenu pour peupler les rectangles
      numbers = [
          [round(random.uniform(0, 100), 3) for _ in range(random.randrange(1, 4))]
          for __ in range(20)
      ]
      
      
      def label_create(canvas, x, y, text):
          # Crée les étiquettes de 50 x 15
          coord = x + 10, y - 15, x + RECT_WIDTH - 20, y
          canvas.create_rectangle(*coord, fill='#aaa', outline='white', width=3)
          canvas.create_text(coord[0] + 25, coord[1] + 7, text=text, fill='green')
      
      
      def content_create(canvas, x, y, numbers, color='#333'):
          x += RECT_WIDTH - 10
          y += 15
          for n in numbers:
              canvas.create_text(x, y, font=('', 8), text=n, fill=color, anchor=tk.NE)
              y += 10
      
      
      window = tk.Tk()
      window.title('SAMARITAIN')
      
      can = tk.Canvas(window, width=550, height=600, bg='green')
      can.pack()
      
      for i in range(20):
          # Rappel le % vaut le reste et le // le quotient de la division entière
          x = START_X + (RECT_WIDTH + MARGIN_HORIZONTAL) * (i % 5)
          y = START_Y + (RECT_HEIGHT + MARGIN_VERTICAL) * (i // 5)
          iid = can.create_rectangle(
              x, y, x + RECT_WIDTH, y + RECT_HEIGHT, fill='white', outline='white'
          )
          label_create(can, x, y, f'n°{i + 1}')
          content_create(can, x, y, numbers[i])
          # print(f'tour {i}: coord rect. = {can.coords(iid)}')
      
      window.mainloop()

      Une autre solution serait de ne plus utiliser de canvas, mais d'autres widgets tkinter, exemple avec labelframe et label.

      import tkinter as tk
      import random
      
      numbers = [
          [round(random.uniform(0, 100), 3) for _ in range(random.randrange(1, 4))]
          for __ in range(20)
      ]
      
      window = tk.Tk()
      window.geometry('600x650')
      window.columnconfigure(0, weight=1)
      window.rowconfigure(0, weight=1)
      
      global_frame = tk.Frame(window, bg='green', padx=25, pady=25)
      global_frame.grid(sticky=tk.NSEW)
      
      # Permet de compartimenter uniformément la frame hor. et vert.
      for i in range(5):
          global_frame.columnconfigure(i, weight=1)
      for i in range(4):
          global_frame.rowconfigure(i, weight=1)
      
      for i in range(20):
          lbl_frame = tk.LabelFrame(
              global_frame, text=f'n°{i + 1}', bg='white', fg='#333'
          )
          lbl_frame.grid(row=i % 4, column=i // 4, sticky=tk.NSEW, padx=10, pady=10)
          lbl_frame.columnconfigure(0, weight=1)
          lbl_frame.rowconfigure(0, weight=1)
          content = tk.Label(
              lbl_frame,
              bg='white',
              fg='#333',
              anchor=tk.NE,
              padx=10,
              pady=15,
              text='\n'.join(str(n) for n in numbers[i]),
          )
          # Le sticky permet d'étirer le label au dimension du labelframe
          content.grid(sticky=tk.NSEW)
      
      window.mainloop()

      Les labelframes disposent de peu d'options d'agrémentations au regard d'un canvas, toutefois il est possible d'utiliser un label pour l'étiquette.

      L'avantage par rapport au canvas est que tout est redimensionnable automatiquement en agrandissant réduisant la fenêtre, ce qui est tout de même appréciable.