如何使用拖放在tkinter网格中交换小部件的位置?

2024-04-20 07:01:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在tkinter中使用拖放来交换网格布局中两个小部件的位置。在鼠标按钮RELEASE-1上,我想获得释放鼠标的小部件(myTextLabel2),这样我就可以使用单击的小部件(myTextLabel1)的行和列更改该小部件的行和列

我试着搜索在x,y位置获取小部件的方法,我能找到的是相反的,获取小部件的位置,而不是相反

以下是我目前的代码:

from tkinter import *
from functools import partial

def changeOrder(widget1,widget2):
    widget1.grid(row=1,column=0)
    widget2.grid(row=0,column=0)

def drag_start(event):
    print(event.x)

def drag_motion(event):
    x = event.x
    y = event.y
    

def drag_release(event):
    x = event.x
    y = event.y
    #I want to get the widget at position x,y, should be myTextLabel2

    #Then swap the rows and columns for myTextLabel2 and myTextLabel1
    

root = Tk()


myTextLabel1 = Label(root,text="Label 1")
myTextLabel1.grid(row=0,column=0,padx=5,pady=5,sticky=E+W+S+N)
myTextLabel1.bind("<Button-1>",drag_start)
myTextLabel1.bind("<B1-Motion>",drag_motion)
myTextLabel1.bind("<ButtonRelease-1>",drag_release)


myTextLabel2 = Label(root,text="Label 2")
myTextLabel2.grid(row=1,column=0,padx=5,pady=5,sticky=E+W+S+N)


myButton = Button(root,text="Change order",command=partial(changeOrder,myTextLabel1,myTextLabel2))
myButton.grid(row=3,column=0,padx=5,pady=5,sticky=E+W+S+N)


root.mainloop()

Tags: textevent部件defcolumnrootlabelgrid
1条回答
网友
1楼 · 发布于 2024-04-20 07:01:12

你可以试试这样的

from tkinter import *
from functools import partial

def changeOrder(widget1,widget2,initial):
    target=widget1.grid_info()
    widget1.grid(row=initial['row'],column=initial['column'])
    widget2.grid(row=target['row'],column=target['column'])

def on_click(event):
    widget=event.widget
    print(widget) 
    if isinstance(widget,Label):
        start=(event.x,event.y)
        grid_info=widget.grid_info()
        widget.bind("<B1-Motion>",lambda event:drag_motion(event,widget,start))
        widget.bind("<ButtonRelease-1>",lambda event:drag_release(event,widget,grid_info))
    else:
        root.unbind("<ButtonRelease-1>")

def drag_motion(event,widget,start):
    x = widget.winfo_x()+event.x-start[0]
    y = widget.winfo_y()+event.y-start[1] 
    widget.lift()
    widget.place(x=x,y=y)

def drag_release(event,widget,grid_info):
    widget.lower()
    x,y=root.winfo_pointerxy()
    target_widget=root.winfo_containing(x,y)
    if isinstance(target_widget,Label):
        changeOrder(target_widget,widget,grid_info)
    else:
        widget.grid(row=grid_info['row'],column=grid_info['column'])

root = Tk()

myTextLabel1 = Label(root,text="Label 1",bg='yellow')
myTextLabel1.grid(row=0,column=0,padx=5,pady=5,sticky=E+W+S+N)

myTextLabel2 = Label(root,text="Label 2",bg='lawngreen')
myTextLabel2.grid(row=1,column=0,padx=5,pady=5,sticky=E+W+S+N)

myButton = Button(root,text="Change order",command=partial(changeOrder,myTextLabel1,myTextLabel2))
myButton.grid(row=3,column=0,padx=5,pady=5,sticky=E+W+S+N)

root.bind("<Button-1>",on_click)

root.mainloop()
  • root.bind("<Button-1>",on_click)已用于使用<Button-1>事件绑定整个窗口,如果单击的小部件是Label的实例,则函数on_click将添加其他2个绑定。标签的grid_info()被存储并相应地传递
  • drag_motion使用place根据运动更改小部件的位置,并使用lift方法将小部件保持在顶部
  • drag_release使用lower方法降低小部件,然后使用winfo_pointerxy方法获取光标的当前位置,并将返回值传递给winfo_containing方法,该方法在鼠标指针下返回小部件

通过将可交换的小部件存储在列表中,然后检查小部件是否位于该列表中,可以替换isinstance逻辑

PS:由于对代码所做的更改,您原始帖子中的按钮将无法工作

相关问题 更多 >