2016-05-17 131 views
1

我想製作一個Python程序,您可以在其中移動小部件。拖放小部件tkinter

這是我的代碼:

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) 

但是,這得到超級出問題和小部件跳來回。

謝謝!

+2

你真的嘗試* *這個代碼?因爲它有多個錯誤,並且不會移動任何東西 - 至少在Mac上的Python 3.5下。 –

+0

你有點擊邊框,而不是文本框 –

回答

5

您正在觀察的行爲是由事件的座標相對於拖動的窗口部件引起的。更新小部件的位置(在絕對座標)與相對座標顯然導致混亂。

爲了解決這個問題,我使用了.winfo_x() and .winfo_y()函數(允許將相對座標轉換爲絕對座標)和Button-1事件來確定拖動開始時光標在控件上的位置。 以下是一個混合使得一個小部件可拖動。

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

     self.drag_start_x = 0 
     self.drag_start_y = 0 
     self.bind("<Button-1>", self.drag_start) 
     self.bind("<B1-Motion>", self.drag_motion) 

    def drag_start(self, event): 
     self.drag_start_x = event.x 
     self.drag_start_y = event.y 

    def drag_motion(self, event): 
     x = self.winfo_x() - self.drag_start_x + event.x 
     y = self.winfo_y() - self.drag_start_y + event.y 
     self.place(x=x, y=y) 

用法:

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

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

main = tk.Tk() 
notesFrame = DnDFrame(main, bd = 4, bg = "grey") 
notesFrame.place(x=10,y=10) 
notes = tk.Text(notesFrame) 
notes.pack() 
+0

謝謝!有效 –

2

Tkinter有一個模塊,在模塊docstring中有記錄。預計它會被一個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]