【问题标题】:tkinter - show image overlay on a canvas image with mouse movetkinter - 通过鼠标移动在画布图像上显示图像叠加
【发布时间】:2017-08-18 18:31:53
【问题描述】:

我有两张完全相同大小的图片。一个是基本背景图像,另一个图像是背景图像的更改版本。我试图在背景图像的顶部显示一个静态大小(例如 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()

背景图片:

改变的图像:

期望的结果:

【问题讨论】:

    标签: python image tkinter tkinter-canvas photoimage


    【解决方案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. "&lt;ButtonPress-1&gt;" 更改为"&lt;Motion&gt;",这样它就可以通过更改鼠标位置来运行。或者将其更改为"&lt;B1-Motion&gt;",以便在您按住左键并移动鼠标时运行。

    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")
      

    你就完成了!正如您所看到的,所有代码都是您自己的代码,并且带有一些香料。我没有经常使用画布,所以我不知道最后一部分是否会继续在另一个之上创建新图像或替换已经存在的图像。所以我不知道它是否是在那里使用的最佳代码,但它可以工作。
    您最好清理这段代码,因为您可以看到move_window 中的很多代码与主循环之前的代码相同
    祝你好运。

    【讨论】:

    • 你让它看起来如此简单!谢谢!
    • 嘿。我在那里犯了一个可怕的错误,我在编辑中修复了它。我再次混淆了 tkinter mainloop 的机制! (每次我回到 tkinter 时都会发生!)。你根本不需要 first_run 的东西。只需删除它,你会没事的。主循环不是那样工作的!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 2019-06-26
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多