画布上方或下方的Tkinter拖放窗口对象

时间:2016-10-27 07:07:28

标签: python tkinter drag-and-drop draggable tkinter-canvas

我制作框架,在其中粘贴几个小部件,然后将它们放在画布上。我的目标是能够以向上或向下的方式拖放这些窗口对象。

我尝试做的是,当用户点击一个手柄并向上或向下移动一个窗口对象时,我希望窗口对象在其上方或下方一旦移出边界阈值就会移开到了。

我试图用Tkinter复制的确切功能可以在这里看到: jQuery Drag and Drop Sortable

Draggable Visual Example

例如,当我向上拖动一个窗口对象时,一旦达到边界阈值,它上面的块就会向下移动以填充下面的相同坐标槽。相同类型的概念适用于向下运动。如果我向下移动,我希望下面的块向上移动以取代当前所选窗口对象移动时上面的插槽。

我的主要问题:如何在当前窗口对象移动时将上方和下方的窗口对象ID relative 获取?

您的第一个想法可能是self.canvas.find_above(item)self.canvas.find_below(item),但我还无法弄清楚如何将上方和下方的窗口对象相对更新为窗口对象在移动时移动。

你的第二个想法可能是标签。例如,使用addtag_above(tag, item)addtag_below(tag, item)添加和删除关于上部和下部对象的标记。我广泛尝试了这一点,但它仍然没有实际意义,因为当移动窗口对象处于运动状态时,我无法更新标签上方和下方。

代码中最相关的部分(注意:这个目的很小,我尝试了很多东西,这个问题已经很长了):

  def StartMove(self, event):
    self.y = event.y
    self.cy = event.widget.nametowidget(event.widget.winfo_parent()).winfo_y()
    self.current = self.canvas.find_closest(10, self.cy)[0]

  def OnMotion(self, event):
    self.canvas.move(self.current, 0, event.y - 10)

  def StopMove(self, event):
    self.y = None

完整代码:

import tkinter as tk

class DragAndDrop(tk.Frame):

  def __init__(self, parent):
    tk.Frame.__init__(self, parent)
    self.parent = parent
    self.parent.columnconfigure(0, weight=1)
    self.grid_columnconfigure(0, weight=1)

    self.block_count = 0

    self.button = tk.Button(self, text='Add', command=self.addblock)
    self.button.grid(row=0, column=0, columnspan=2, sticky='new')

    self.container = tk.Frame(self)
    self.container.grid(row=1, column=0, sticky='nsew')

    self.canvas = tk.Canvas(self.container, width=200, height=450)
    self.scrollbar = tk.Scrollbar(self.container,
                                  orient='vertical',command=self.canvas.yview)
    self.canvas.config(yscrollcommand=self.scrollbar.set)
    self.canvas.grid(row=0, column=0, sticky='nsew')
    self.scrollbar.grid(row=0, column=1, sticky='nse')

    self.container.bind('<Configure>', self.handle_scroll)

  def addblock(self):
    self.block = tk.Frame(self.canvas, bd=1, relief='solid')
    self.block.columnconfigure(0, weight=1)

    self.grip = tk.Label(self.block, bitmap="gray25")
    self.grip.grid(row=0, column=0, sticky='w')

    self.grip.bind("<ButtonPress-1>", self.StartMove)
    self.grip.bind("<ButtonRelease-1>", self.StopMove)
    self.grip.bind("<B1-Motion>", self.OnMotion)

    self.canvas.create_window((0, (self.block_count*25)),
                              window=self.block, anchor="nw",
                              width=200, height=24)
    self.block_count += 1
    self.canvas.configure(scrollregion=self.canvas.bbox("all"))

  def handle_scroll(self, event):
    self.canvas.configure(scrollregion=self.canvas.bbox("all"))

  def StartMove(self, event):
    self.y = event.y
    self.cy = event.widget.nametowidget(event.widget.winfo_parent()).winfo_y()
    self.current = self.canvas.find_closest(10, self.cy)[0]

  def OnMotion(self, event):
    self.canvas.move(self.current, 0, event.y - 10)

  def StopMove(self, event):
    self.y = None

root = tk.Tk()
app = DragAndDrop(root)
app.grid(row=0, column=0, sticky='ew')
root.mainloop()

1 个答案:

答案 0 :(得分:1)

  

我的主要问题:如何获取上下窗口对象   在当前窗口对象运动时相对于当前窗口对象的ID

在我看来,最简单的解决方案是首先生成所有块及其坐标的列表。然后,按Y坐标对列表进行排序。在绑定中,找到列表中最后一个块,鼠标位于鼠标上方,Y坐标位于鼠标下方。