Canvas.create_image(),可拖动图像似乎没有从其位置移动?

发布于 2025-01-16 16:30:11 字数 1591 浏览 1 评论 0原文

我目前正在使用 Tkinter,我正在尝试制作一个可拖动的画布图像,代码是我从 另一个堆栈溢出问题,第二个是特别的。当我使用 tk.Frame() 时,代码对我有用,但它给出了 Canvas.create_image() 的错误。所以我对它进行了一些编辑,但现在当我拖动它时,它似乎完全移动了图像

我的代码:

from tkinter import *
import pyautogui

x,y=pyautogui.size()
tk = Tk()

c = Canvas(tk, width=x, height=y)
c.place(x=-2,y=-3)
img = ImageTk.PhotoImage(PIL.Image.open(r"Data\backgrounds\background.jpg"))
c.create_image(0, 0, image=img, anchor=NW)

def command6():
  print("command6")
  
def make_draggable(widget,btn="<Button-1>",motion="<B1-Motion>"):
    def __draggable__(widget):
        c.tag_bind(btn,btn,on_drag_start)
        c.tag_bind(motion,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.move(widget,x, y)

    __draggable__(widget)

APP_6 = r'apps\File.png'
APP_6 = PIL.Image.open(APP_6)
APP_6 = APP_6.resize((48,48),PIL.Image.ANTIALIAS)
APP_6 = ImageTk.PhotoImage(APP_6)

image_6 = ImageTk.PhotoImage(PIL.Image.open(r"apps\File.png"))
image_id_6 = c.create_image(48,48, image=APP_6)
c.move(image_id_6, 1,y-735)

c.tag_bind(image_id_6, '<Button-1>',command6)
make_draggable(image_id_6)    


tk.mainloop()

这不会在控制台中给出任何错误或任何不需要的输出。

Im working with Tkinter currently and im trying to make an draggable canvas image, the code i've "made"/edited from another stack overflow question, the second one to be particular. There code works for me when im using tk.Frame(), but it gives an error for Canvas.create_image(). So i edited it a little but now it seems to to be moving the image at all when i drag it

My code:

from tkinter import *
import pyautogui

x,y=pyautogui.size()
tk = Tk()

c = Canvas(tk, width=x, height=y)
c.place(x=-2,y=-3)
img = ImageTk.PhotoImage(PIL.Image.open(r"Data\backgrounds\background.jpg"))
c.create_image(0, 0, image=img, anchor=NW)

def command6():
  print("command6")
  
def make_draggable(widget,btn="<Button-1>",motion="<B1-Motion>"):
    def __draggable__(widget):
        c.tag_bind(btn,btn,on_drag_start)
        c.tag_bind(motion,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.move(widget,x, y)

    __draggable__(widget)

APP_6 = r'apps\File.png'
APP_6 = PIL.Image.open(APP_6)
APP_6 = APP_6.resize((48,48),PIL.Image.ANTIALIAS)
APP_6 = ImageTk.PhotoImage(APP_6)

image_6 = ImageTk.PhotoImage(PIL.Image.open(r"apps\File.png"))
image_id_6 = c.create_image(48,48, image=APP_6)
c.move(image_id_6, 1,y-735)

c.tag_bind(image_id_6, '<Button-1>',command6)
make_draggable(image_id_6)    


tk.mainloop()

this gives no errors or any unwanted output in the console.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

来世叙缘 2025-01-23 16:30:12

make_draggable() 函数内部存在一些问题:

  • .tag_bind() 的第一个参数是画布项的项 ID。对于您的情况,它是 make_draggable()widget 参数。因此,以下行:
        c.tag_bind(btn,btn,on_drag_start)
        c.tag_bind(motion,motion,on_drag_motion)

应更改为

        c.tag_bind(widget, btn, on_drag_start)
        c.tag_bind(widget, motion, on_drag_motion)

Same apply to c.move(...) inside on_drag_motion()

  • 移动画布项目的逻辑/计算是错误的

下面是修改后的 make_draggable() 函数:

def make_draggable(widget, btn="<Button-1>", motion="<B1-Motion>"):
    def __draggable__(widget):
        c.tag_bind(widget, btn, on_drag_start)
        c.tag_bind(widget, motion, on_drag_motion)
        c._item_id = widget # save the item ID for later use

    def on_drag_start(event):
        widget = event.widget
        # get the top-left coordinates of the selected item
        x, y, *_ = widget.bbox(widget._item_id)
        # save the offset of current mouse position from the top-left coordinates
        widget._dx = event.x - x
        widget._dy = event.y - y

    def on_drag_motion(event):
        widget = event.widget
        # calculate the top-left coordinates of the item that the item to be moved to
        x = event.x - widget._dx
        y = event.y - widget._dy
        # move the item using moveto() instead of move()
        widget.moveto(widget._item_id, x, y)

    __draggable__(widget)

由于上述逻辑仅适用于最后一次调用 make_draggable() 的项目。最好使用类而不是函数:

class make_draggable():
    def __init__(self, item_id, btn="<Button-1>", motion="<B1-Motion>"):
        self.item_id = item_id
        c.tag_bind(item_id, btn, self.on_drag_start, add=True)
        c.tag_bind(item_id, motion, self.on_drag_motion, add=True)

    def on_drag_start(self, event):
        x, y, *_ = event.widget.bbox(self.item_id)
        self.dx, self.dy = event.x-x, event.y-y

    def on_drag_motion(self, event):
        event.widget.moveto(self.item_id, event.x-self.dx, event.y-self.dy)

There are few issues inside make_draggable() function:

  • first argument of .tag_bind() is the item ID of a canvas item. For your case, it is widget argument of make_draggable(). So the following lines:
        c.tag_bind(btn,btn,on_drag_start)
        c.tag_bind(motion,motion,on_drag_motion)

should be changed to

        c.tag_bind(widget, btn, on_drag_start)
        c.tag_bind(widget, motion, on_drag_motion)

Same apply to c.move(...) inside on_drag_motion()

  • the logic/calculation on moving the canvas item is wrong

Below is the modified make_draggable() function:

def make_draggable(widget, btn="<Button-1>", motion="<B1-Motion>"):
    def __draggable__(widget):
        c.tag_bind(widget, btn, on_drag_start)
        c.tag_bind(widget, motion, on_drag_motion)
        c._item_id = widget # save the item ID for later use

    def on_drag_start(event):
        widget = event.widget
        # get the top-left coordinates of the selected item
        x, y, *_ = widget.bbox(widget._item_id)
        # save the offset of current mouse position from the top-left coordinates
        widget._dx = event.x - x
        widget._dy = event.y - y

    def on_drag_motion(event):
        widget = event.widget
        # calculate the top-left coordinates of the item that the item to be moved to
        x = event.x - widget._dx
        y = event.y - widget._dy
        # move the item using moveto() instead of move()
        widget.moveto(widget._item_id, x, y)

    __draggable__(widget)

As the above logic applies only on the item of the last call of make_draggable(). It is better to use class instead of function:

class make_draggable():
    def __init__(self, item_id, btn="<Button-1>", motion="<B1-Motion>"):
        self.item_id = item_id
        c.tag_bind(item_id, btn, self.on_drag_start, add=True)
        c.tag_bind(item_id, motion, self.on_drag_motion, add=True)

    def on_drag_start(self, event):
        x, y, *_ = event.widget.bbox(self.item_id)
        self.dx, self.dy = event.x-x, event.y-y

    def on_drag_motion(self, event):
        event.widget.moveto(self.item_id, event.x-self.dx, event.y-self.dy)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文