6

我正在尝试制作一个能够拖放到画布上的列表框。我以前做过拖放,但它只是在 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
4

1 回答 1

4

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

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

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

在放置时,您需要使用画布的canvasxcanvasy方法将鼠标的坐标转换为画布坐标。event.x而不是以and开头event.y(相对于列表框),使用该winfo_pointerxy方法获取鼠标的屏幕坐标,然后做一些数学运算。

这是一个如何做drop的例子:

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"))
于 2013-05-20T11:16:55.570 回答