python-3.x - 如何通过角落拖动画布上的对象?以及如何将对象分开一次?
问题描述
我正在尝试创建一个简单的程序,您可以在其中通过拖动来在 tkinter 的画布上移动多个对象。首先,我从 2 个正方形开始。但是,我面临两个问题:
每当我单击对象时,它都会以鼠标指针为中心(指针始终位于正方形的中间)。如何通过单击位置拖动对象(例如按角拖动)?
一旦我用一个方格穿过另一个方格,第二个方格就会停留在顶部,不能再分开了。对象具有相同的大小。
有什么简单的解决方案吗?感谢您提供任何帮助或建议。
我的代码:
import tkinter
c = tkinter.Canvas(width = 400, height = 300)
c.pack()
d = 25 #size of square
x, x2 = 100, 200
y, y2 = 100, 200
rect = c.create_rectangle(x-d, y-d, x+d, y+d, fill = 'blue') #first square
rect2 = c.create_rectangle(x2-d, y2-d, x2+d, y2+d, fill = 'red') #second square
def drag(event): #drag by holding mouse button 1
global x, y, x2, y2, xt, yt, x2t, y2t
xt, yt = event.x, event.y #1st square movement coords
x2t, y2t = event.x, event.y #2nd square movement coords
if xt in range(x-d, x+d):
if yt in range(y-d, y+d):
c.coords(rect, xt-d, yt-d, xt+d, yt+d) #coords update of 1st square
x, y = xt, yt
if x2t in range(x2-d, x2+d):
if y2t in range(y2-d, y2+d):
c.coords(rect2, x2t-d, y2t-d, x2t+d, y2t+d) #coords update of 2nd square
x2, y2 = x2t, y2t
c.bind('<B1-Motion>', drag)
tkinter.mainloop()
解决方案
有两个问题:
1-要通过角捕获对象,您需要将对象位置偏移其边界框尺寸的一半。(请参阅通过右下角捕获对象的示例;您可以通过更改所用偏移的符号来更改角。)
2-为了在拖动对象时区分对象,您需要在已捕获对象时“停用”回调。这个例子展示了如何做我认为必要的家务。(但可能有更好的方法,内置 tkinter、IDK)
import tkinter
captured = None
def capture(event):
global captured
print('captured')
if captured is None:
captured = event.widget.find_closest(event.x, event.y)
def release(event):
global captured
print('released')
captured = None
def drag(event): # drag by holding mouse button 1
global captured
if captured is None:
print(f'captured {event.widget.find_closest(event.x, event.y)}')
captured = event.widget.find_closest(event.x, event.y)
print(f'captured: {captured}')
else:
x0, y0, x1, y1 = c.bbox(captured)
xt, yt = event.x + (x0 - x1) // 2, event.y + (y0 - y1) // 2 # 1st square movement coords
c.coords(captured, xt-d, yt-d, xt+d, yt+d) # coords update of 1st square
if __name__ == '__main__':
c = tkinter.Canvas(width = 400, height = 300)
c.pack()
d = 25 # size of square
x, x2 = 100, 200
y, y2 = 100, 200
rect1 = c.create_rectangle(x-d, y-d, x+d, y+d, fill='blue', tags='r1') # first square
rect2 = c.create_rectangle(x2-d, y2-d, x2+d, y2+d, fill='red', tags='r2') # second square
c.bind('<Button-1>', capture)
c.bind('<ButtonRelease-1>', release)
c.bind('<B1-Motion>', drag)
tkinter.mainloop()
推荐阅读
- ruby - 无法加载此类文件 - 'nokogiri\nokogiri' ruby 2.7
- python - 如何使用 python 构建视频聊天应用程序
- c - 更改 RBG 值似乎在 C 中不起作用
- ios - 以下两种方法的 Apple 组合等效项是什么?
- python - Docker 数据库访问被拒绝
- ruby - 在 ruby 中进行可重新启动的下载
- checkout - Design Sync 不会还原本地更改
- javascript - 将 JWT 令牌用于用户和应用程序
- ios - 为什么 Swift 对象在 Objective-C 代码中被声明/未声明为属性时表现不同?
- python - 使用Python进行语音分析)如何在x轴上及时查看语音文件的分析结果,在y轴上查看分贝数?