[英]Tkinter <Enter> bind looping forever
我正在嘗試為事件制作一個可選擇的鍾面。 我有我的 Canvas 對象,並創建了一堆里面有文字的圓圈。
我想在鼠標懸停時反轉圓圈和文本的顏色。
問題是:
代碼:
from tkinter import *
from math import sin, cos, pi
root = Tk()
class TimePicker(Canvas):
def __init__(self, master, **kwargs):
self.tformat = kwargs.pop('format', 24)
self.width, self.height, self.radious = kwargs['width'], kwargs['height'], rd = (kwargs.pop('radious', 100)*2, )*3
self.radious /=4
assert self.tformat in [12, 24], "Time Format must be '12' or '24'"
super(TimePicker, self).__init__(master, **kwargs)
self.active_line = None
self.create_center_circle(self.width/2, self.height/2, self.radious*2, fill="white", outline="#000", width=1)
self.circle_numbers(self.width/2, self.height/2, self.radious+5, 10, [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 'Helvetica 11 bold', "Hours")
self.circle_numbers(self.width/2, self.height/2, self.radious*2-15, 10, [0, 15, 30, 45], 'Helvetica 11 bold', "Minutes")
def create_center_circle(self, x, y, r, **kwargs):
return super().create_oval(x-r, y-r, x+r, y+r, **kwargs)
def create_circle_arc(self, x, y, r, **kwargs):
if "start" in kwargs and "end" in kwargs:
kwargs["extent"] = kwargs["end"] - kwargs["start"]
del kwargs["end"]
return super().create_arc(x-r, y-r, x+r, y+r, **kwargs)
def circle_numbers(self, x: int, y: int, r: int, cr:int, numbers: list, font: str, tp:str):
_angle = 360/len(numbers)
for n in numbers:
ax = r * sin(pi * 2 * (360-_angle*n-180) / 360);
ay = r * cos(pi * 2 * (360-_angle*n-180) / 360);
tag = f'{tp}:{str(n)}'
cl = self.create_center_circle(x+ax, y+ay, cr, fill="white", outline="#000", width=1, tag=tag)
tx = self.create_text(x+ax, y+ay, text=str(n).zfill(2), fill="black", font=(font), tag='tx'+tag )
self.tag_bind(f'{tp}:{str(n)}', '<Enter>', lambda e=Event(), c=(x+ax, y+ay), t=tag, s=True: self._hover(e, c, s, t))
self.tag_bind(f'{tp}:{str(n)}', '<Leave>', lambda e=Event(), c=(x+ax, y+ay), t=tag, s=False: self._hover(e, c, s, t))
self.tag_bind(f'{tp}:{str(n)}', '<Button-1>', lambda e=Event(), c=cl, s=tx, n=n, t=tp,: self._set_number(e, c, s, n, t))
def _hover(self, event, coords, state, tag):
print('hover')
if state: # If hovering inside the object
print("hovering")
cl =event.widget.find_withtag(tag) ## for the text and circle with the hovered tag
tx = event.widget.find_withtag('tx'+tag)
self.itemconfigure(cl, fill='black')
self.itemconfigure(tx, fill="white")
self.active_line = self.create_line(self.width/2, self.height/2, coords[0], coords[1], fill="black", width=2) ##create new line
else: ##If left the object
print("exited")
if self.active_line is not None: ##if there is a line
cl = event.widget.find_withtag(tag) ## for the text and circle in the tag
tx = event.widget.find_withtag('tx'+tag)
self.itemconfigure(cl, fill='white')
self.itemconfigure(tx, fill="black")
self.delete(self.active_line)
self.active_line = None
def _set_number(self, event, cl, tx, number, tp):
print('set', cl, tx, number, tp)
if __name__ == '__main__':
tp=TimePicker(root, format=24, background="red", radious=100)
tp.pack(side=TOP)
root.mainloop()
我在測試時意識到,當創建一條線並且該線恰好位於鼠標光標下方時,將為文本觸發<Leave>
事件,然后刪除導致<Enter>
事件的線再次在光標下繪制線.
對此的解決方案是使線更短並且不允許它進入與鼠標相同的空間。
作為快速修復,我將線縮短了 20%,但是完整的解決方案需要檢查線是否在鼠標下方並觸發標志以防止線被破壞。
def _hover(self, event, coords, state, tag):
...
self.itemconfigure(tx, fill="white")
dx = (1 - 0.8) * self.width/2 + 0.8 * coords[0]
dy = (1 - 0.8) * self.height/2 + 0.8 * coords[1]
self.active_line = self.create_line(self.width/2, self.height/2, dx, dy, fill="#0797FF", width=2, tag=None) ##create new line
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.