Canvas 项 event_generate
Canvas item event_generate
我会尝试 运行 我的命令 nothing()
在 item
的嵌套 class 中,即使用户在项目附近单击也是如此,但它变成了无限循环。
所以我的想法是将鼠标移动到项目上,单击项目并返回到起始位置。为了保护一些行,我将它运行k 解决了这里这段代码的问题:
item = canvas.find_closest(canvas.canvasx(event.x),
canvas.canvasy(event.y))[0]
canvas.event_generate('<Motion>', warp=True, x=x, y=y)
canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
canvas.after(20,canvas.event_generate('<ButtonRelease-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery()))
我想保持结构如下,使用 tk.Frame 的子 class,网格我的 canvas 并定义用这段代码完成的项目这里:
class my_figure(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
# DownFrame
self.button = tk.Button(self, text='add', command=self.add)
self.button.grid(column=0, row=0)
self.body = tk.Frame(self, relief='sunken')
self.Display = tk.Canvas(self.body)
self.Display.bind("<Button-1>", self.click)
self.body.grid(column=0, row=1, sticky='nswe')
self.Display.grid(column=0, row=0,
sticky='nswe')
class item(object):
def __init__(self,canvas, x1, y1,x2, y2):
rec = canvas.create_rectangle(x1,y1,x2,y2)
canvas.tag_bind(rec,'<Button-1>',self.nothing)
def nothing(self, event):
print('nothing')
其余代码都是垃圾,只是为了展示一些东西。
可在此处找到可执行示例:
import tkinter as tk
root = tk.Tk()
class my_figure(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
# DownFrame
self.button = tk.Button(self, text='add', command=self.add)
self.button.grid(column=0, row=0)
self.body = tk.Frame(self, relief='sunken')
self.Display = tk.Canvas(self.body)
self.Display.bind("<Button-1>", self.click)
self.body.grid(column=0, row=1, sticky='nswe')
self.Display.grid(column=0, row=0,
sticky='nswe')
self.x = tk.IntVar()
self.x2 = tk.IntVar()
self.y = tk.IntVar()
self.y2 = tk.IntVar()
self.x.set(10)
self.x2.set(50)
self.y.set(10)
self.y2.set(10)
def click(self, event):
canvas = event.widget
item = canvas.find_closest(canvas.canvasx(event.x),
canvas.canvasy(event.y))[0]
self.coord = (canvas.coords(item))
x = self.coord[0]
y = self.coord[1]
print(item)
print(self.coord)
canvas.event_generate('<Motion>', warp=True, x=x, y=y)
canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
canvas.after(20,canvas.event_generate('<ButtonRelease-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery()))
def add(self):
x = self.item(self.Display,self.x.get(),self.y.get(),self.x2.get(),self.y2.get())
self.old_x = self.x.get()
self.old_x2 = self.x2.get()
self.old_y = self.y.get()
self.old_y2 = self.y2.get()
self.x.set(self.old_x+40)
self.x2.set(self.old_x2+40)
self.y.set(self.old_y+40)
self.y2.set(self.old_y2+80)
class item(object):
def __init__(self,canvas, x1, y1,x2, y2):
rec = canvas.create_rectangle(x1,y1,x2,y2)
canvas.tag_bind(rec,'<Button-1>',self.nothing)
def nothing(self, event):
print('nothing')
figure = my_figure(root)
figure.grid()
root.mainloop()
您可能过去做过一些事情并想分享经验,或者您有比这更好的想法,我们欢迎一切。
您可能对我的参考文献感兴趣:
https://wiki.tcl-lang.org/page/event+generate
http://mars.cs.utu.fi/BioInfer/files/doc/private/Tkinter.Canvas-class.html
https://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.event_generate-method
问题在这里:
canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
当生成一个 <Button-1>
事件时,<Button-1>
也会调用 click
函数 again.Then 它会无限调用它。
一个简单的解决方案是检查自定义状态变量(也许您需要做一些修改):
import tkinter as tk
root = tk.Tk()
class my_figure(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
# DownFrame
self.button = tk.Button(self, text='add', command=self.add)
self.button.grid(column=0, row=0)
self.body = tk.Frame(self, relief='sunken')
self.Display = tk.Canvas(self.body)
self.Display.bind("<Button-1>", self.click)
self.body.grid(column=0, row=1, sticky='nswe')
self.Display.grid(column=0, row=0,
sticky='nswe')
self.x = tk.IntVar()
self.x2 = tk.IntVar()
self.y = tk.IntVar()
self.y2 = tk.IntVar()
self.x.set(10)
self.x2.set(50)
self.y.set(10)
self.y2.set(10)
# add here
self.check = True
def click(self, event):
canvas = event.widget
item = canvas.find_closest(canvas.canvasx(event.x),
canvas.canvasy(event.y))[0]
self.coord = (canvas.coords(item))
x = self.coord[0]
y = self.coord[1]
print(item)
print(self.coord)
canvas.event_generate('<Motion>', warp=True, x=x, y=y)
if self.check:
# when call it twice, pass it.
self.check = False
self.check = canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
canvas.after(20, canvas.event_generate('<ButtonRelease-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery()))
# restore.
self.check = True
def add(self):
x = self.item(self.Display, self.x.get(), self.y.get(), self.x2.get(), self.y2.get())
self.old_x = self.x.get()
self.old_x2 = self.x2.get()
self.old_y = self.y.get()
self.old_y2 = self.y2.get()
self.x.set(self.old_x + 40)
self.x2.set(self.old_x2 + 40)
self.y.set(self.old_y + 40)
self.y2.set(self.old_y2 + 80)
class item(object):
def __init__(self, canvas, x1, y1, x2, y2):
rec = canvas.create_rectangle(x1, y1, x2, y2)
canvas.tag_bind(rec, '<Button-1>', self.nothing)
def nothing(self, event):
print('nothing')
figure = my_figure(root)
figure.grid()
root.mainloop()
问题的根源是您需要在 item
的实例上调用与 canvas 上的矩形相关的方法,并且您需要能够做到这一点仅基于矩形 ID。您将需要创建一种将矩形 ID 转换为 item
class.
实例的方法
最简单的解决方案是:
- 将
item
的实例保存在字典中,其中键是矩形 id
- 提供一个接口,用于根据矩形 id 获取
item
的实例。
保存每个实例非常简单:创建一个 class 字典变量,然后将实例添加到 __init__
中的字典中。这是一个简单的例子:
class Item(object):
_instances = {}
def __init__(self,canvas, x1, y1,x2, y2):
self.item_id = canvas.create_rectangle(x1,y1,x2,y2)
self._instances[self.item_id] = self
因此,编写一个 class 方法可以 return 任何 canvas 项目 id 的 Item
的实例是微不足道的:
@classmethod
def get_item(cls, item_id):
return cls._instances.get(item_id, None)
这是一个完整的工作示例,当您通过调用实例上的方法单击它时,它会更改最近元素的背景。我稍微调整了 item
以记住 canvas,并且我正在使用 PEP8 命名准则。
import tkinter as tk
import random
root = tk.Tk()
canvas = tk.Canvas(root, width=200, height=200, bg="bisque")
canvas.pack(fill="both", expand=True)
class Item(object):
_instances = {}
def __init__(self,canvas, x1, y1,x2, y2):
self.canvas = canvas
self.item_id = canvas.create_rectangle(x1,y1,x2,y2)
self._instances[self.item_id] = self
@classmethod
def get_item(cls, item_id):
return cls._instances.get(item_id, None)
def nothing(self):
self.canvas.itemconfigure(self.item_id, fill="red")
for i in range(20):
x1 = random.randint(0, 175)
y1 = random.randint(0, 175)
x2 = x1 + random.randint(10,20)
y2 = y1 + random.randint(10,20)
Item(canvas, x1, y1, x2, y2)
def click_closest(event):
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
item_id = canvas.find_closest(x, y)[0]
item = Item.get_item(item_id)
item.nothing()
canvas.bind("<1>", click_closest)
root.mainloop()
这不一定是解决问题的最佳或最有效的方法,但它给出了如何将 python 对象与 canvas 项相关联的一般概念。
我会尝试 运行 我的命令 nothing()
在 item
的嵌套 class 中,即使用户在项目附近单击也是如此,但它变成了无限循环。
所以我的想法是将鼠标移动到项目上,单击项目并返回到起始位置。为了保护一些行,我将它运行k 解决了这里这段代码的问题:
item = canvas.find_closest(canvas.canvasx(event.x),
canvas.canvasy(event.y))[0]
canvas.event_generate('<Motion>', warp=True, x=x, y=y)
canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
canvas.after(20,canvas.event_generate('<ButtonRelease-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery()))
我想保持结构如下,使用 tk.Frame 的子 class,网格我的 canvas 并定义用这段代码完成的项目这里:
class my_figure(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
# DownFrame
self.button = tk.Button(self, text='add', command=self.add)
self.button.grid(column=0, row=0)
self.body = tk.Frame(self, relief='sunken')
self.Display = tk.Canvas(self.body)
self.Display.bind("<Button-1>", self.click)
self.body.grid(column=0, row=1, sticky='nswe')
self.Display.grid(column=0, row=0,
sticky='nswe')
class item(object):
def __init__(self,canvas, x1, y1,x2, y2):
rec = canvas.create_rectangle(x1,y1,x2,y2)
canvas.tag_bind(rec,'<Button-1>',self.nothing)
def nothing(self, event):
print('nothing')
其余代码都是垃圾,只是为了展示一些东西。 可在此处找到可执行示例:
import tkinter as tk
root = tk.Tk()
class my_figure(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
# DownFrame
self.button = tk.Button(self, text='add', command=self.add)
self.button.grid(column=0, row=0)
self.body = tk.Frame(self, relief='sunken')
self.Display = tk.Canvas(self.body)
self.Display.bind("<Button-1>", self.click)
self.body.grid(column=0, row=1, sticky='nswe')
self.Display.grid(column=0, row=0,
sticky='nswe')
self.x = tk.IntVar()
self.x2 = tk.IntVar()
self.y = tk.IntVar()
self.y2 = tk.IntVar()
self.x.set(10)
self.x2.set(50)
self.y.set(10)
self.y2.set(10)
def click(self, event):
canvas = event.widget
item = canvas.find_closest(canvas.canvasx(event.x),
canvas.canvasy(event.y))[0]
self.coord = (canvas.coords(item))
x = self.coord[0]
y = self.coord[1]
print(item)
print(self.coord)
canvas.event_generate('<Motion>', warp=True, x=x, y=y)
canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
canvas.after(20,canvas.event_generate('<ButtonRelease-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery()))
def add(self):
x = self.item(self.Display,self.x.get(),self.y.get(),self.x2.get(),self.y2.get())
self.old_x = self.x.get()
self.old_x2 = self.x2.get()
self.old_y = self.y.get()
self.old_y2 = self.y2.get()
self.x.set(self.old_x+40)
self.x2.set(self.old_x2+40)
self.y.set(self.old_y+40)
self.y2.set(self.old_y2+80)
class item(object):
def __init__(self,canvas, x1, y1,x2, y2):
rec = canvas.create_rectangle(x1,y1,x2,y2)
canvas.tag_bind(rec,'<Button-1>',self.nothing)
def nothing(self, event):
print('nothing')
figure = my_figure(root)
figure.grid()
root.mainloop()
您可能过去做过一些事情并想分享经验,或者您有比这更好的想法,我们欢迎一切。
您可能对我的参考文献感兴趣:
https://wiki.tcl-lang.org/page/event+generate
http://mars.cs.utu.fi/BioInfer/files/doc/private/Tkinter.Canvas-class.html
https://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.event_generate-method
问题在这里:
canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
当生成一个 <Button-1>
事件时,<Button-1>
也会调用 click
函数 again.Then 它会无限调用它。
一个简单的解决方案是检查自定义状态变量(也许您需要做一些修改):
import tkinter as tk
root = tk.Tk()
class my_figure(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
# DownFrame
self.button = tk.Button(self, text='add', command=self.add)
self.button.grid(column=0, row=0)
self.body = tk.Frame(self, relief='sunken')
self.Display = tk.Canvas(self.body)
self.Display.bind("<Button-1>", self.click)
self.body.grid(column=0, row=1, sticky='nswe')
self.Display.grid(column=0, row=0,
sticky='nswe')
self.x = tk.IntVar()
self.x2 = tk.IntVar()
self.y = tk.IntVar()
self.y2 = tk.IntVar()
self.x.set(10)
self.x2.set(50)
self.y.set(10)
self.y2.set(10)
# add here
self.check = True
def click(self, event):
canvas = event.widget
item = canvas.find_closest(canvas.canvasx(event.x),
canvas.canvasy(event.y))[0]
self.coord = (canvas.coords(item))
x = self.coord[0]
y = self.coord[1]
print(item)
print(self.coord)
canvas.event_generate('<Motion>', warp=True, x=x, y=y)
if self.check:
# when call it twice, pass it.
self.check = False
self.check = canvas.event_generate('<Button-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery())
canvas.after(20, canvas.event_generate('<ButtonRelease-1>',
x=root.winfo_pointerx(),
y=root.winfo_pointery()))
# restore.
self.check = True
def add(self):
x = self.item(self.Display, self.x.get(), self.y.get(), self.x2.get(), self.y2.get())
self.old_x = self.x.get()
self.old_x2 = self.x2.get()
self.old_y = self.y.get()
self.old_y2 = self.y2.get()
self.x.set(self.old_x + 40)
self.x2.set(self.old_x2 + 40)
self.y.set(self.old_y + 40)
self.y2.set(self.old_y2 + 80)
class item(object):
def __init__(self, canvas, x1, y1, x2, y2):
rec = canvas.create_rectangle(x1, y1, x2, y2)
canvas.tag_bind(rec, '<Button-1>', self.nothing)
def nothing(self, event):
print('nothing')
figure = my_figure(root)
figure.grid()
root.mainloop()
问题的根源是您需要在 item
的实例上调用与 canvas 上的矩形相关的方法,并且您需要能够做到这一点仅基于矩形 ID。您将需要创建一种将矩形 ID 转换为 item
class.
最简单的解决方案是:
- 将
item
的实例保存在字典中,其中键是矩形 id - 提供一个接口,用于根据矩形 id 获取
item
的实例。
保存每个实例非常简单:创建一个 class 字典变量,然后将实例添加到 __init__
中的字典中。这是一个简单的例子:
class Item(object):
_instances = {}
def __init__(self,canvas, x1, y1,x2, y2):
self.item_id = canvas.create_rectangle(x1,y1,x2,y2)
self._instances[self.item_id] = self
因此,编写一个 class 方法可以 return 任何 canvas 项目 id 的 Item
的实例是微不足道的:
@classmethod
def get_item(cls, item_id):
return cls._instances.get(item_id, None)
这是一个完整的工作示例,当您通过调用实例上的方法单击它时,它会更改最近元素的背景。我稍微调整了 item
以记住 canvas,并且我正在使用 PEP8 命名准则。
import tkinter as tk
import random
root = tk.Tk()
canvas = tk.Canvas(root, width=200, height=200, bg="bisque")
canvas.pack(fill="both", expand=True)
class Item(object):
_instances = {}
def __init__(self,canvas, x1, y1,x2, y2):
self.canvas = canvas
self.item_id = canvas.create_rectangle(x1,y1,x2,y2)
self._instances[self.item_id] = self
@classmethod
def get_item(cls, item_id):
return cls._instances.get(item_id, None)
def nothing(self):
self.canvas.itemconfigure(self.item_id, fill="red")
for i in range(20):
x1 = random.randint(0, 175)
y1 = random.randint(0, 175)
x2 = x1 + random.randint(10,20)
y2 = y1 + random.randint(10,20)
Item(canvas, x1, y1, x2, y2)
def click_closest(event):
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
item_id = canvas.find_closest(x, y)[0]
item = Item.get_item(item_id)
item.nothing()
canvas.bind("<1>", click_closest)
root.mainloop()
这不一定是解决问题的最佳或最有效的方法,但它给出了如何将 python 对象与 canvas 项相关联的一般概念。