拖动并单击管理 tkinter

问题描述 投票:0回答:1

我徒劳地尝试允许用户通过单击并拖动将网格的多个框变黑,但它只使第一个单击的框变黑,该怎么做?

我的代码非常丰富,我不会发布所有内容,但这是我的问题的功能示例

这是我的代码的摘录:

import tkinter as tk
from tkinter import ttk


class GrilleFenetre(tk.Tk):
    """ interface graphique pour resoudre les hanjies """
    def __init__(self):
        super().__init__()
        self.title("Hanjie Solver")
        self.minsize(800, 500)
        self.content = ttk.Frame(self, padding=(3,3,12,12))
        self.grille_frame = ttk.Frame(self.content, borderwidth=2, relief="solid")
        self.content.grid(row=0, column=0, sticky="nsew")
        self.grille_frame.grid(row=1, column=3, columnspan=3, sticky="nsew", padx=5)
        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)
        self.content.columnconfigure(0, weight=1)
        self.content.columnconfigure(1, weight=1)
        self.content.columnconfigure(2, weight=1)
        self.content.columnconfigure(3, weight=3, minsize=100)
        self.content.rowconfigure(1, weight=3)
        
        self.creer_hanjie()

    def creer_hanjie(self):
            """ affiche une grille de cases blanches """
            #self.resoudre_bouton['state'] = 'normal'
            #self.flag_crea = False
            self.hanjie = []
            self.rows = 10
            self.cols = 10
            self.hanjie = [[0] * self.cols for _ in range(self.rows)]
            self.cellule_taille = 50
            #self.grille_frame = ttk.Frame(self.content)
            
            for r in range(self.rows):
                
                for c in range(self.cols):
                    self.cell = tk.Frame(self.grille_frame, borderwidth=1, relief="solid", bg="white", width=self.cellule_taille, height=self.cellule_taille)
                    # detection du click sur une case  
                    self.cell.bind("<B1-Motion>", lambda event, row=r, col=c: self.click_cases(event, row, col))             
                    self.hanjie[r][c] = self.cell
                    
                    self.cell.grid(row=r+1, column=c+1, sticky="nsew")
            
            self.grille_frame.grid(row=1, column=3, columnspan=2, sticky="nsew", padx=10, pady=10)
            #self.update_interface(2)
            
            
    #%% click cases
    def click_cases(self, event, row, col):
        """ change la couleur de la case cliquée """
        #print(row, col)
        case = self.hanjie[row][col]
        couleur_actuelle = case.cget("bg")
        nouvelle_couleur = "black" if couleur_actuelle == "white" else "white"
        case.configure(bg=nouvelle_couleur)
            
if __name__ == "__main__":
    fenetre = GrilleFenetre()
    fenetre.geometry("800x600+350+150")  # Taille initiale de la fenêtre
    fenetre.mainloop()

我想尝试检索鼠标指针的坐标,但由于我不知道盒子的确切坐标,所以有点复杂......

python tkinter mouseevent
1个回答
0
投票

即使您为每个单元格的运动事件创建了绑定,但在处理运动事件时,该事件始终只会为收到按钮按下的单元格触发。这意味着您需要计算鼠标下的小部件,而不是依赖于传入的行和列,因为当您移动鼠标时,传入的值不会改变。

您可以使用

winfo_containing
获取光标下的小部件,并将事件的根坐标传递给它。然后,您可以使用该信息来了解要更改哪个单元格。

第 1 步:停止将行和列传递给事件处理程序

for c in range(self.cols):
    ...
    self.cell.bind("<B1-Motion>", click_cases)
    ...

第二步:修改回调以获取光标下的小部件。

这将无条件地将颜色设置为黑色,但您可以添加一些逻辑来切换它。然而,由于回调可能在单个单元上发生数十次,这将导致大量令人不快的闪烁。

我不知道您真正想要发生什么,但这个简化的示例展示了在运动事件的回调中确定鼠标下方的小部件的基本技术。

def click_cases(self, event):
    case = event.widget.winfo_containing(event.x_root, event.y_root)
    case.configure(bg="black")

© www.soinside.com 2019 - 2024. All rights reserved.