【问题标题】:tkinter - How to drag and drop widgets?tkinter - 如何拖放小部件?
【发布时间】:2016-09-13 18:47:08
【问题描述】:

我正在尝试制作一个 Python 程序,您可以在其中移动小部件。

这是我的代码:

import tkinter as tk 
main = tk.Tk()
notesFrame = tk.Frame(main, bd = 4, bg = "a6a6a6")
notesFrame.place(x=10,y=10)
notes = tk.Text(notesFrame)
notes.pack()
notesFrame.bind("<B1-Motion>", lambda event: notesFrame.place(x = event.x, y = event.y)

但是,这会出现超级故障,并且小部件会来回跳跃。

【问题讨论】:

  • 你真的尝试过 this 代码吗?因为它有多个错误,并且似乎没有移动任何东西 - 至少在 Mac 上的 Python 3.5 下。
  • 你点击的是边框,而不是文本框

标签: python tkinter drag-and-drop


【解决方案1】:

您观察到的行为是由于事件的坐标相对于拖动的小部件这一事实引起的。用相对坐标更新小部件的位置(在绝对坐标中)显然会导致混乱。

为了解决这个问题,我使用了.winfo_x() and .winfo_y() 函数(允许将相对坐标转换为绝对坐标)和Button-1 事件来确定拖动开始时光标在小部件上的位置。

这是一个使小部件可拖动的函数:

def make_draggable(widget):
    widget.bind("<Button-1>", on_drag_start)
    widget.bind("<B1-Motion>", on_drag_motion)

def on_drag_start(event):
    widget = event.widget
    widget._drag_start_x = event.x
    widget._drag_start_y = event.y

def on_drag_motion(event):
    widget = event.widget
    x = widget.winfo_x() - widget._drag_start_x + event.x
    y = widget.winfo_y() - widget._drag_start_y + event.y
    widget.place(x=x, y=y)

可以这样使用:

main = tk.Tk()

frame = tk.Frame(main, bd=4, bg="grey")
frame.place(x=10, y=10)
make_draggable(frame)

notes = tk.Text(frame)
notes.pack()

如果你想采用更面向对象的方法,你可以写一个mixin,让一个类的所有实例都可以拖动:

class DragDropMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        make_draggable(self)

用法:

# As always when it comes to mixins, make sure to
# inherit from DragDropMixin FIRST!
class DnDFrame(DragDropMixin, tk.Frame):
    pass

# This wouldn't work:
# class DnDFrame(tk.Frame, DragDropMixin):
#     pass

main = tk.Tk()

frame = DnDFrame(main, bd=4, bg="grey")
frame.place(x=10, y=10)

notes = tk.Text(frame)
notes.pack()

【讨论】:

  • 动议1:什么都不做,动议2:换地方。我认为这是一个小错误。
【解决方案2】:

Tkinter 有一个用于此的模块,记录在模块文档字符串中。预计它将被 tk dnd 模块取代,但这并没有发生。我从未尝试过。在 SO 中搜索 [tkinter] dnd 会返回 this page。下面是文档字符串的开头。

>>> from tkinter import dnd
>>> help(dnd)
Help on module tkinter.dnd in tkinter:

NAME
    tkinter.dnd - Drag-and-drop support for Tkinter.

DESCRIPTION
    This is very preliminary.  I currently only support dnd *within* one
    application, between different windows (or within the same window).
[snip]

【讨论】:

  • 整个文档字符串可以在source code中查看。
猜你喜欢
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 2014-06-15
  • 1970-01-01
相关资源
最近更新 更多