【问题标题】:How to implement a mouse hovering callback on canvas items in tkinter?如何在 tkinter 中的画布项目上实现鼠标悬停回调?
【发布时间】:2016-12-08 21:34:34
【问题描述】:

我使用以下在互联网上找到的代码在 python 中实现鼠标悬停动作:

from tkinter import *
import numpy as np

class rect:
    def __init__(self, root):
        self.root = root
        self.size = IntVar()
        self.canvas = Canvas(self.root, width=800, height=300)
        self.scale = Scale(self.root, orient=HORIZONTAL, from_=3, to=20, tickinterval=1, variable=self.size)
        self.scale.bind('<ButtonRelease>', self.show)
        self.canvas.bind('<Motion>', self.motion)
        self.board = []
        self.array = np.zeros((self.scale.get(),self.scale.get())).tolist()
        self.canvas.pack()
        self.scale.pack()

    def motion(self,event):
        if self.canvas.find_withtag(CURRENT):
            current_color = self.canvas.itemcget(CURRENT, 'fill')
            self.canvas.itemconfig(CURRENT, fill="cyan")
            self.canvas.update_idletasks()
            self.canvas.after(150)
            self.canvas.itemconfig(CURRENT, fill=current_color)

    def show(self,event):
        self.canvas.delete('all')
        x = 50
        y = 50
        row = []
        self.board.clear()
        for i in range(self.scale.get()):
            row = []
            for j in range(self.scale.get()):
                rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red')
                x += 50
                row.append(rectangle)
            x -= j*50
            y +=50
            self.board.append(row)
        print(self.board)

root = Tk()
a = rect(root)
root.mainloop()

执行的问题是项目的颜色仅在有限的时间内变为蓝色。

每当我进入画布区域时,我都需要更改画布中每个项目的颜色并保持蓝色,直到鼠标离开该项目。

【问题讨论】:

  • event.widget.find_closest(event.x, event.y) 返回一个索引号,但如果随机创建,您会遇到很多麻烦。

标签: python tkinter tkinter-canvas mousehover


【解决方案1】:

您可以在创建矩形时传递参数activefill

来自effboot.org

当鼠标指针移到项目上时使用的填充颜色,如果 不同于填充。

为此,请替换:

rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red')

作者:

rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red', activefill='cyan')

这消除了将 Motion 绑定到您的画布的需要,并且还使代码明显更短:

from tkinter import *
import numpy as np

class rect:
    def __init__(self, root):
        self.root = root
        self.size = IntVar()
        self.canvas = Canvas(self.root, width=800, height=300)
        self.scale = Scale(self.root, orient=HORIZONTAL, from_=3, to=20, tickinterval=1, variable=self.size)
        self.scale.bind('<ButtonRelease>', self.show)
        self.board = []
        self.array = np.zeros((self.scale.get(),self.scale.get())).tolist()
        self.canvas.pack()
        self.scale.pack()

    def show(self,event):
        self.canvas.delete('all')
        x = 50
        y = 50
        row = []
        self.board.clear()
        for i in range(self.scale.get()):
            row = []
            for j in range(self.scale.get()):
                rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red', activefill='cyan')
                x += 50
                row.append(rectangle)
            x -= j*50
            y +=50
            self.board.append(row)
        print(self.board)

root = Tk()
a = rect(root)
root.mainloop()

【讨论】:

  • 谢谢伙计。那真的很酷。它优化了我的代码。
【解决方案2】:

我更改了motion 方法并将self.last = None 添加到__init__ 方法:

from tkinter import *
import numpy as np

class rect:
    def __init__(self, root):
        self.root = root
        self.size = IntVar()
        self.canvas = Canvas(self.root, width=800, height=300)
        self.scale = Scale(self.root, orient=HORIZONTAL, from_=3, to=20, tickinterval=1, variable=self.size)
        self.scale.bind('<ButtonRelease>', self.show)
        self.canvas.bind('<Motion>', self.motion)
        self.board = []
        self.array = np.zeros((self.scale.get(),self.scale.get())).tolist()
        self.canvas.pack()
        self.scale.pack()
        self.last = None

    def motion(self, event):
        temp = self.canvas.find_withtag(CURRENT)
        if temp == self.last:
            self.canvas.itemconfig(CURRENT, fill="cyan")
            self.canvas.update_idletasks()
        else:
            self.canvas.itemconfig(self.last, fill="red")
        self.last = temp

    def show(self,event):
        self.canvas.delete('all')
        x = 50
        y = 50
        row = []
        self.board.clear()
        for i in range(self.scale.get()):
            row = []
            for j in range(self.scale.get()):
                rectangle = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill='red')
                x += 50
                row.append(rectangle)
            x -= j*50
            y +=50
            self.board.append(row)
        print(self.board)

root = Tk()
a = rect(root)
root.mainloop()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多