【问题标题】:A differen "Drag and Drop" images in Tkinter (Python 3.x)Tkinter(Python 3.x)中不同的“拖放”图像
【发布时间】:2013-06-29 01:52:44
【问题描述】:

我试图让我的程序的用户可以从一个小部件中拖动一个图像并将其放到另一个小部件中,而不会将图像从其第一个位置移除。

我想为此使用TopLevel。在单击+拖动事件时,包含相同图像的TopLevel 将在event.x 和event.y 位置上的单击图像正上方弹出。然后它会随着鼠标改变它的位置,只有在ButtonRelease-1 时TopLevel 才会被销毁。

如果在主 x 和 y 坐标上触发了 Button Release 事件,对应于我的其他小部件(在本例中为画布)的位置,那么它将使用 event.x 和 event.y 触发 canvas.create_image() .

我面临的问题是:

  1. 一次只能出现 1 个TopLevel,但我没有成功限制它。当我单击并拖动鼠标时,几个窗口重叠。

  2. 我不能让Toplevel.geometry 使用绑定事件的 x 和 y 位置。

  3. 如何使Toplevel 显示与用户单击相同的图像,而没有幻数和变量?

到目前为止,这是我的代码:

class animalImgList():

    def __init__(self, a):
        #Constructor
        initX = 75
        initY =  40

        animalList = ['pig2.jpg', 'pig3.jpg', 'pig4.jpg']

        for a in animalList:
            vars(self)[a+'img'] = PIL.Image.open(a)

            vars(self)[a+'tkimg'] = PIL.ImageTk.PhotoImage(vars(self)[a+'img'])

            vars(self)[a+'labelName'] = Label(anmlCanvas, image=vars(self)[a+'tkimg'])
            vars(self)[a+'canvasImg'] = anmlCanvas.create_image(initX, initY,image=(vars(self)[a+'tkimg']))
            initY = initY + 70

            anmlImgList = []
            anmlImgList.append(vars(self)[a+'canvasImg'])

            imgTags = anmlCanvas.addtag_all("img")
            anmlCanvas.tag_bind("img", "<Button-1>", self.createImg)

    def createImg(self, event):

        newImg = Toplevel(root)
        newImg.geometry("50x40"+"+"+ x+"+"+y)

        newImgMsg = Message(newImg, text="This is supposed to be an image")
        newImgMsg.pack()

        newImg.update_idletasks()
        newImg.overrideredirect(True)

        createImgOpen = True

        if createImgOpen == True:
            pass

【问题讨论】:

    标签: python events binding tkinter python-3.3


    【解决方案1】:

    在两个画布之间拖动图像而不从第一个画布中删除图像。

    思路如下:

    • 当用户点击画布can1(click1函数)时:

      • 使用can1.find_closest获取用户点击的项目
      • 用can1.itemcget获取它的图像
      • 创建一个包含图像的顶层
      • 绑定鼠标移动沿顶层拖动:为此您需要使用event.x_root 和event.y_root 来更改顶层的几何形状。
    • 当用户释放鼠标左键时(release函数):

      • 取消绑定鼠标动作
      • 如果顶层在画布can2 内,则在鼠标位置在can2 中创建图像
      • 破坏顶层

    这样,只能有一个顶层,因为每次释放按钮时,顶层都会被销毁。

    代码如下:

    import tkinter as tk
    
    class DragToplevel(tk.Toplevel):
        def __init__(self, master, image, x, y):
            tk.Toplevel.__init__(self, master)
            self.overrideredirect(True)
            self.geometry('+%i+%i' % (x, y))
    
            self.image = image
    
            self.label = tk.Label(self, image=image, bg='red')
            self.label.pack()
    
        def move(self, x, y):
            self.geometry('+%i+%i' % (x, y))
    
    
    root = tk.Tk()
    
    can1 = tk.Canvas(root, width=300, height=300, bg='white')
    can2 = tk.Canvas(root, width=300, height=300, bg='white')
    
    can1.pack(side='left')
    can2.pack(side='right')
    root.geometry('800x800')
    
    im = tk.PhotoImage('tux', master=root, file='/home/juliette/Images/tux_mini.png')
    drag_id = ''
    dragged = None
    can1.create_image(100, 200, image=im)
    
    def click1(event):
        global drag_id, dragged
        items = can1.find_closest(event.x, event.y)
        if items:
            image = can1.itemcget(items[0], 'image')
            dragged = DragToplevel(root, image, event.x_root, event.y_root)
            drag_id = root.bind('<Motion>', lambda e: dragged.move(e.x_root, e.y_root))
    
    
    def release(event):
        global drag_id, dragged
        root.unbind('<Motion>',  drag_id)
        drag_id = ""
        xr, yr = event.x_root, event.y_root
        x2, y2 = can2.winfo_rootx(), can2.winfo_rooty()
        w2, h2 = can2.winfo_width(), can2.winfo_height()
        if dragged and xr >= x2 and xr < x2 + w2 and yr >= y2 and yr < y2 + h2:
            can2.create_image(xr - x2, yr - y2, image=dragged.image, anchor='nw')
        if dragged:
            dragged.destroy()
            dragged = None
    
    
    can1.bind('<ButtonPress-1>', click1)
    root.bind('<ButtonRelease-1>', release)
    
    root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-03
      • 1970-01-01
      • 2018-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-06
      相关资源
      最近更新 更多