tkinter列表框拖放

Pis*_*ete 5 drag-and-drop tkinter

我正在尝试制作一个能够拖放到画布上的列表框.我之前已经完成了拖放操作,但它只是在canvas.create_text之间松散地基于我在这里找到的这个跳棋程序的代码.我已经看到了一些关于拖放列表框的问题,但它们只涉及更改列表框中元素的顺序.我正在处理的是一个列表框,其中包含一个名称列表,以及一个画布上包含一些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
Run Code Online (Sandbox Code Playgroud)

Bry*_*ley 4

拖放的关键归结为需要做三件事:

  • 绑定<ButtonPress-1>选择要拖动的项目
  • 绑定<B1-Motion>以进行拖动
  • 绑定<ButtonRelease-1>以进行放置

这些都不需要任何子类化。所有这些绑定都位于列表框小部件上。您可能需要创建一个Toplevel其中包含文本标签的实例,并删除窗口装饰(使用wm_overrideredirect(True))来表示正在拖动的项目。

在放置时,您需要使用画布的canvasxcanvasy方法将鼠标坐标转换为画布坐标。event.x不要从and开始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"))
Run Code Online (Sandbox Code Playgroud)