tkinter - 如何拖放小部件? [英] tkinter - How to drag and drop widgets?

查看:40
本文介绍了tkinter - 如何拖放小部件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个 Python 程序,您可以在其中移动小部件.

I am trying to make a Python program in which you can move around widgets.

这是我的代码:

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)

但是,这会变得非常小故障,并且小部件来回跳跃.

But, this gets super glitchy and the widget jumps back and forth.

推荐答案

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

The behavior you're observing is caused by the fact that the event's coordinates are relative to the dragged widget. Updating the widget's position (in absolute coordinates) with relative coordinates obviously results in chaos.

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

To fix this, I've used the .winfo_x() and .winfo_y() functions (which allow to turn the relative coordinates into absolute ones), and the Button-1 event to determine the cursor's location on the widget when the drag starts.

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

Here's a function that makes a widget draggable:

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 使类的所有实例都可拖动:


If you want to take a more object-oriented approach, you can write a mixin that makes all instances of a class draggable:

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()

这篇关于tkinter - 如何拖放小部件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆