我正在尝试让我的程序的用户能够从小部件中拖动图像并将其放入另一个小部件中,而无需将图像从其第一个位置移除。
我想为此使用 TopLevel
。在单击+拖动事件时,包含相同图像的 TopLevel
将在 event.x
和 event.y< 上弹出被单击图像的正上方
位置。然后它会随着鼠标改变它的位置,只有在 ButtonRelease-1
时 TopLevel
才会被销毁。
如果 Button Release 事件是在主 x 和 y 坐标上触发的,对应于我的其他小部件(在本例中是 Canvas )的位置,那么它将触发 canvas.create_image()
使用 event.x
和 event.y
。
我面临的问题是:
一次只能出现 1 个
TopLevel
,但我没有成功限制它。当我单击并拖动鼠标时,多个窗口重叠。我无法让
Toplevel.geometry
使用绑定(bind)事件的 x 和 y 位置。如何让
Toplevel
显示与用户点击相同的图像,而不需要魔数(Magic Number)和变量?
到目前为止,这是我的代码:
class animalImgList():
def __init__(self, a):
#Constructor
initX = 75
initY = 40
animalList = ['pig2.jpg', 'pig3.jpg', 'pig4.jpg']
for a in animalList:
vars(self)[a+'img'] = PIL.Image.open(a)
vars(self)[a+'tkimg'] = PIL.ImageTk.PhotoImage(vars(self)[a+'img'])
vars(self)[a+'labelName'] = Label(anmlCanvas, image=vars(self)[a+'tkimg'])
vars(self)[a+'canvasImg'] = anmlCanvas.create_image(initX, initY,image=(vars(self)[a+'tkimg']))
initY = initY + 70
anmlImgList = []
anmlImgList.append(vars(self)[a+'canvasImg'])
imgTags = anmlCanvas.addtag_all("img")
anmlCanvas.tag_bind("img", "<Button-1>", self.createImg)
def createImg(self, event):
newImg = Toplevel(root)
newImg.geometry("50x40"+"+"+ x+"+"+y)
newImgMsg = Message(newImg, text="This is supposed to be an image")
newImgMsg.pack()
newImg.update_idletasks()
newImg.overrideredirect(True)
createImgOpen = True
if createImgOpen == True:
pass
最佳答案
在不从第一个 Canvas 中移除图像的情况下,在两个 Canvas 之间拖动图像。
思路如下:
当用户点击 Canvas
can1
时(click1
函数):- 通过
can1.find_closest
获取用户点击的项目 - 使用
can1.itemcget
获取它的图像 - 创建一个包含图像的顶层
- 绑定(bind)鼠标运动以沿顶层拖动:为此,您需要使用
event.x_root
和event.y_root
来更改顶层的几何形状。
- 通过
当用户释放鼠标左键时(
release
函数):- 解绑鼠标移动
- 如果顶层在 Canvas
can2
内,在can2
中鼠标位置创建图像 - 摧毁顶层
这样,就只能有一个顶层,因为每次释放按钮时,顶层都会被销毁。
代码如下:
import tkinter as tk
class DragToplevel(tk.Toplevel):
def __init__(self, master, image, x, y):
tk.Toplevel.__init__(self, master)
self.overrideredirect(True)
self.geometry('+%i+%i' % (x, y))
self.image = image
self.label = tk.Label(self, image=image, bg='red')
self.label.pack()
def move(self, x, y):
self.geometry('+%i+%i' % (x, y))
root = tk.Tk()
can1 = tk.Canvas(root, width=300, height=300, bg='white')
can2 = tk.Canvas(root, width=300, height=300, bg='white')
can1.pack(side='left')
can2.pack(side='right')
root.geometry('800x800')
im = tk.PhotoImage('tux', master=root, file='/home/juliette/Images/tux_mini.png')
drag_id = ''
dragged = None
can1.create_image(100, 200, image=im)
def click1(event):
global drag_id, dragged
items = can1.find_closest(event.x, event.y)
if items:
image = can1.itemcget(items[0], 'image')
dragged = DragToplevel(root, image, event.x_root, event.y_root)
drag_id = root.bind('<Motion>', lambda e: dragged.move(e.x_root, e.y_root))
def release(event):
global drag_id, dragged
root.unbind('<Motion>', drag_id)
drag_id = ""
xr, yr = event.x_root, event.y_root
x2, y2 = can2.winfo_rootx(), can2.winfo_rooty()
w2, h2 = can2.winfo_width(), can2.winfo_height()
if dragged and xr >= x2 and xr < x2 + w2 and yr >= y2 and yr < y2 + h2:
can2.create_image(xr - x2, yr - y2, image=dragged.image, anchor='nw')
if dragged:
dragged.destroy()
dragged = None
can1.bind('<ButtonPress-1>', click1)
root.bind('<ButtonRelease-1>', release)
root.mainloop()
关于python - Tkinter (Python 3.x) 中的不同 "Drag and Drop"图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17413011/