最后的目标是建立一个图表,这是y轴加上主要领域。主字段由单独的框组成(比如20 x20像素)。至少有500 x500个盒子,我希望更多。主字段应该是可拖动的。
在Stackoverflow的帮助下,我选择将图像放在主字段画布上,而不仅仅是标签。使用canvas.move()而不是在拖动时重绘元素。y轴也是一个画布,但带有标签。
这个解决方案对于小画布(100 x100个元素)是可以的,但是当拖动500 x500个元素的画布时,我遇到了延迟(滞后,惯性)。
然后我尝试添加额外的画布,这是内部的。这个想法是在画布上移动内部画布(带有图像),而不仅仅是在单个画布上移动图像。
因此,内部画布必须放置在窗口内。我在Windows上贴上了“canv”标签。并在调用move函数时引用它。
但我可以捕捉窗口只是点击一个小的1像素的区域周围的内部画布周长。
当点击主字段本身时,为了拖动图表的主字段,而不仅仅是1-pxl画布轮廓,应该改变什么?或者解决方案体系结构发生了变化?
需要记住的是,y轴必须与主磁场的垂直运动同步。我设法通过以前的解决方案实现了这种同步,但不是通过当前的解决方案。
import tkinter as tk
from functools import partial
class DraggableCanvas(tk.Canvas):
def __init__(self, master=None, **kwargs):
super().__init__(master, **kwargs)
self.start_pos = 0, 0
self.bind('<Button>', self.on_drag_start)
self.image = tk.PhotoImage(file='images\\image_ .png') # icon-like 20*20 pxls image
self.tag_bind('canv', '<B1-Motion>', partial(self.on_drag_motion, 'canv'))
self.add_images()
self.add_internal_canvas()
def on_drag_start(self, event):
self.start_pos = event.x, event.y
def add_internal_canvas(self):
int_canvas = tk.Canvas(self, width=200, height=200)
self.create_window(50, 25, anchor='nw', window=int_canvas, tags='canv')
for i in range(100):
for j in range(100):
int_canvas.create_image(10+j*21, 10+i*21, image=self.image)
def add_images(self):
pass
# for i in range(100):
# for j in range(100):
# self.create_image(10+j*21, 10+i*21, image=self.image, tags='img')
def on_drag_motion(self, imgs_tag, event):
self.tag_raise(imgs_tag)
self.move(imgs_tag, event.x - self.start_pos[0], event.y - self.start_pos[1])
self.on_drag_start(event)
def main():
root = tk.Tk()
canvas1 = tk.Canvas(root, bg='#303040', width=100, height=480)
canvas1.pack(side='left', anchor='n')
for i in range(10):
lbl = tk.Label(canvas1, text='y_axis', width=5, bg='#303030', fg='white')
lbl.pack(anchor='n')
DraggableCanvas(root, bg='grey', width=750, height=480).pack(anchor='nw')
root.mainloop()
if __name__ == "__main__":
main()
1条答案
按热度按时间vawmfj5a1#
我有这个
我认为你的代码的问题是
int_canvas
吞下了所有发生在它内部的鼠标事件,这样on_drag_start
和on_drag_motion
就不会被调用。为了解决这个问题,我绑定到int_canvas
,并在on_drag_start
和on_drag_motion
中稍微改变了计算。我不认为我的代码是非常有效的,所以如果有人想更新它,随时这样做。现在它有一个问题,你可以把画布拖到屏幕外面。我通过使用
max(..., 0)
添加了一个小的修复,但这只适用于左侧/顶部。至于滞后的问题,我在我的电脑上没有看到,但如果你仍然看到它,试着减少
tkinter
必须处理的东西的数量。例如,您可以使用PIL
将某些图像合并合并,并将其显示为1个单个图像。