我正在尝试创建一个能够拖放到画布上的列表框。我之前已经完成了拖放操作,但它只是在canvas.create_text之间松散地根据我发现的这个跳棋程序的代码here.我看到了一些关于拖放列表框的问题但是它们只是处理更改列表框中元素的顺序。我正在处理的是一个列表框,其中包含一个名称列表,以及一个画布上包含一些create_text对象的画布,我希望能够将列表框中的名称拖到画布上。如果我需要创建一个Listbox子类,但我不确定从那里去哪里。
所以我有一个DialogWindow(Toplevel的子类),并在DialogWindow中有我的画布和列表框。我想出了一种从列表框中获取名称的方法:当我点击一个名字时,我将它转换为canvas.create_text对象,然后拖动它。我的问题是下降。我尝试使用canvas.canvasx转换为画布坐标,但它对我没用。 x和y仍在列表框坐标中。
def onRelease(self, event):
x = self.canvas.canvasx(event.x)
y = self.canvas.canvasx(event.y)
print(event.x, event.y)
print(x, y) #Prints the same thing as the previous line
答案 0 :(得分:3)
拖放的关键归结为需要做三件事:
<ButtonPress-1>
以选择要拖动的项目<B1-Motion>
进行拖动<ButtonRelease-1>
以执行放置这些都不需要任何子类化。所有这些绑定都在列表框小部件上。您可能希望创建一个Toplevel
的实例,其中包含文本标签,并删除窗口装饰(使用wm_overrideredirect(True)
)来表示正在拖动的项目。
在下拉列表中,您需要使用画布的canvasx
和canvasy
方法将鼠标坐标转换为画布坐标。不是从event.x
和event.y
(相对于列表框)开始,而是使用winfo_pointerxy
方法获取鼠标的屏幕坐标,然后做一些数学运算。
以下是如何进行放弃的示例:
def _on_drag_drop(self, event):
i = self.listbox.curselection()[0]
text = self.listbox.get(i)
wx, wy = self.canvas.winfo_rootx(), self.canvas.winfo_rooty()
x,y = self.winfo_pointerxy()
cx = self.canvas.canvasx(x-wx)
cy = self.canvas.canvasy(y-wy)
self.canvas.create_text(cx,cy,text=text, anchor="sw")
self.canvas.configure(scrollregion=self.canvas.bbox("all"))