tkinter - 使用鼠标移动在画布图像上显示图像叠加

时间:2017-08-18 18:31:53

标签: python image tkinter tkinter-canvas photoimage

我有两张尺寸完全相同的图片。一个是基本背景图像,另一个图像是背景图像的改变版本。我试图在背景图像的顶部显示一个静态大小(如100,100)的改变图像的窗口,它们在鼠标移动的任何地方排成一行。在基本图像上覆盖改变的图像的移动窗口的排序。我一直试图修改我在Stack Overflow上找到的一些基本代码,但似乎无法弄清楚如何修改它以获得所需的结果。如果你认为我是以错误的方式解决这个问题,或者如果我错过了某个地方,那么请建议一种替代方法。我对tkinter很新。另外,我不需要下面的图像示例中显示的坐标系。只是图像本身就是好的。

from tkinter import *
from PIL import ImageTk, Image
from scipy.misc import imread

event2canvas = lambda e, c: (c.canvasx(e.x), c.canvasy(e.y))

# function to be called when mouse is moved
def move_window(event):
    # outputting x and y coords to console
    cx, cy = event2canvas(event, canvas)
    print("(%d, %d) / (%d, %d)" % (event.x, event.y, cx, cy))


if __name__ == "__main__":
    root = Tk()

    #setting up a tkinter canvas with scrollbars
    frame = Frame(root, bd=2, relief=SUNKEN)
    frame.grid_rowconfigure(0, weight=1)
    frame.grid_columnconfigure(0, weight=1)
    xscroll = Scrollbar(frame, orient=HORIZONTAL)
    xscroll.grid(row=1, column=0, sticky=E+W)
    yscroll = Scrollbar(frame)
    yscroll.grid(row=0, column=1, sticky=N+S)
    canvas = Canvas(frame, bd=0, xscrollcommand=xscroll.set, yscrollcommand=yscroll.set)
    canvas.grid(row=0, column=0, sticky=N+S+E+W)
    xscroll.config(command=canvas.xview)
    yscroll.config(command=canvas.yview)
    frame.pack(fill=BOTH,expand=1)

    # loading background and altered image into numpy array.
    background_image_data = imread("images/original.png", mode="L")
    foreground_image_data = imread("images/altered.png", mode="L")

    # Here is where the mouse coordinates should be injected to move the window over the background image
    window_data = foreground_image_data[500:600, 500:600]
    background_image_data[500:600, 500:600] = window_data

    img = ImageTk.PhotoImage(Image.fromarray(background_image_data))
    canvas.create_image(0, 0,image=img,anchor="nw")
    canvas.config(scrollregion=canvas.bbox(ALL), width=img.width(), height=img.height())

    test = canvas.bind("<ButtonPress-1>", move_window)

    root.mainloop()

背景图片: enter image description here

改变图像: enter image description here

期望的结果: enter image description here

1 个答案:

答案 0 :(得分:1)

你实际上几乎完成了所有这些。你只需要重新定位一些东西,并在这里和那里添加一些东西(我不打算以干净的方式去做,否则我必须改变更多的东西。你可以自己以后自己做,不要有重复的行你的代码):

  1. 更改代码的这一部分:

    # loading background and altered image into numpy array.
    background_image_data = imread("images/original.png", mode="L")
    foreground_image_data = imread("images/altered.png", mode="L")
    
    # Here is where the mouse coordinates should be injected to move the window over the background image
    window_data = foreground_image_data[500:600, 500:600]
    background_image_data[500:600, 500:600] = window_data
    
    img = ImageTk.PhotoImage(Image.fromarray(background_image_data))
    canvas.create_image(0, 0,image=img,anchor="nw")
    canvas.config(scrollregion=canvas.bbox(ALL), width=img.width(), height=img.height()) 
    

    到此:

    # loading background and altered image into numpy array.
    background_image_data = imread("images/original.png", mode="L")
    foreground_image_data = imread("images/altered.png", mode="L")
    '''Shouldn't change the original background image because
    that way the changes will be permanent'''
    bg_img = background_image_data.copy() 
    # Here is where the mouse coordinates should be injected to move the window over the background image
    x,y,wh = (50,50,100)
    window_data = foreground_image_data[y:y+wh,x:x+wh]
    bg_img[y:y+wh,x:x+wh] = window_data
    img = ImageTk.PhotoImage(Image.fromarray(bg_img))
    canvas.create_image(0, 0,image=img,anchor="nw")
    canvas.config(scrollregion=canvas.bbox(ALL), width=img.width(), height=img.height())
    
  2. "<ButtonPress-1>"更改为"<Motion>",以便通过更改鼠标位置来运行它。或者将其更改为"<B1-Motion>",这样只要按住左键并移动鼠标,它就会运行。

  3. 更改此内容:

    def move_window(event):
        cx, cy = event2canvas(event, canvas)
    

    对此:

    def move_window(event):
        global img
        cx, cy = event2canvas(event, canvas)
        x,y,wh = (int(cx),int(cy),100)
        window_data = foreground_image_data[y:y+wh,x:x+wh]
        bg_img = background_image_data.copy()
        bg_img[y:y+wh,x:x+wh] = window_data
        img = ImageTk.PhotoImage(Image.fromarray(bg_img))
        canvas.create_image(0, 0,image=img,anchor="nw")
    
  4. 你已经完成了!正如你所看到的那样,所有你自己的代码都只是四处移动,并带有一些香料。我没有非常使用画布,所以我不知道最后一部分是否会继续在另一部分上创建新图像或者替换已经存在的图像。所以我不知道它是否是在那里使用的最佳代码,但它确实有用 您最好清理此代码,因为您可以看到move_window中的许多代码与主循环之前的代码相同 祝你好运。