Bonjour,

J'ai un problème de décalage de coordonnées entre la souris et le canvas...
Dans le code ci-dessous, je crée un quadrillage dans un canvas qui commence à x=30 et y=30.
mais lorsque je place la souris à x=30 et y=30, la souris est légèrement décalé, du coup lorsque je clique pour noircir une case, ce n'est pas forcément la bonne qui se noircit...
Si on clique sur create grid au démarrage, il n'y a pas de problème, mais si on clique ensuite sur matrice, ça se décale...
De plus, je ne comprends pas pourquoi il reste des spinbox affichés alors qu'ils sont censés être effacés par le .delete("all").
y-a-t-il une erreur dans mon code, ou est-ce un bug de mon ordi (je travaille sur un macbook air M2) ?

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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Feb  1 23:04:57 2024
 
@author: jojo
"""
import tkinter as tk
from tkinter import ttk
 
 
root = tk.Tk()
btn_frame = tk.Frame(root)
btn_frame.grid(row=0, column=0, columnspan=3)
grille_frame = tk.Canvas(root, width=600, height=600)
grille_frame.grid(row=1, column = 0)
yscrollbar_grille = ttk.Scrollbar(root, orient="vertical", command=grille_frame.yview)
yscrollbar_grille.grid(row=0, column=3, rowspan=3, sticky="ns")
xscrollbar_grille = ttk.Scrollbar(root, orient="horizontal", command=grille_frame.xview)
xscrollbar_grille.grid(row=2, column=0, columnspan=3, sticky="ew")
grille_frame.config(yscrollcommand=yscrollbar_grille.set, xscrollcommand=xscrollbar_grille.set)
rows = 12
cols = 12
cell_size = 40
 
x = 30
y = 30
 
def zoom():
    grille_frame.scale("all", 30, 30, 0.5, 0.5)
 
scale_btn = tk.Button(btn_frame, text="scale", command=zoom)
scale_btn.grid(row=0, column=0)
 
def mouse_position(event):
    grille_frame.event_generate("<Motion>", warp=True, x=30, y=30)
    print("mouse position winfo", root.winfo_pointerxy())
    print("mouse position on canvas", event.x, event.y)
    print("mouse postition on screen", event.x_root, event.y_root)
    print("canvas postition", grille_frame.bbox("all"))
 
 
root.bind("<Key>", mouse_position)
def matrice():
    grille_frame.delete("all")
    y = 30
    for r in range(rows):
        x = 30
 
        spinbox_row = tk.Spinbox(grille_frame, from_=0, to=cols, width=2)
        grille_frame.create_window((x, y+cell_size/2), window=spinbox_row, anchor="e")
 
        temp = []
        for c in range(cols):
            cell = grille_frame.create_rectangle((x, y), (x + cell_size, y + cell_size), fill="white", outline= "black")
            temp.append(cell)
            x = x + cell_size
        y = y + cell_size
 
    x = y = 30
    for c in range(cols):
        spinbox_col = tk.Spinbox(grille_frame, from_=0, to=rows, width=2)
        grille_frame.create_window((x+cell_size/2, y), window=spinbox_col, anchor="s")
        x = x + cell_size
 
    grille_frame.update_idletasks()
    grille_frame.config(scrollregion=grille_frame.bbox("all"))
 
matrice_btn = tk.Button(btn_frame, text="Matrice", command=matrice)
matrice_btn.grid(row=0, column=2)
def creer_hanjie():
    """ affiche une grille de cases blanches """
    grille_frame.delete("all")
    x = 30
    y = 30
 
    for r in range(rows):
        x = 30
        for c in range(cols):
            cell = grille_frame.create_rectangle((x, y), (x + cell_size, y + cell_size ), fill="white", outline= "black")
            x = x + cell_size
            #print("coordonnées case:", grille_frame.coords(cell))           
        y = y + cell_size
    root.bind("<Button-1>", click_1case)
 
    grille_frame.update_idletasks()
    print("canvaas taille", grille_frame.bbox("all"))
    grille_frame.config(scrollregion=grille_frame.bbox("all"))
 
grille_btn = tk.Button(btn_frame, text="create grid", command=creer_hanjie)
grille_btn.grid(row=0, column=1)
 
def click_1case(event):
    """ change la couleur de la case par click simple, 1 case à la fois """
    print("clic souris", event.x, event.y)
    case = grille_frame.find_closest(event.x, event.y)
    couleur_actuelle = grille_frame.itemcget(case, "fill")
    if couleur_actuelle == "white":
        nouvelle_couleur = "black"
    else:
        nouvelle_couleur = "white"
    grille_frame.itemconfigure(case, fill=nouvelle_couleur)
 
root.mainloop()