0

我正在尝试创建一个可以从 python 代码触发的屏幕截图区域工具。

它在第一次通话时有效,但在第二次通话时出现以下错误: TclError: image "pyimage2" doesn't exist

只有在我重新启动内核后才能工作,但只有一次,然后出现同样的错误..

我包括了下面的所有代码。有 python-mss 作为依赖项(和 tkinter 在 linux 上)

import os
from tkinter import Tk, Canvas, PhotoImage, YES, BOTH, NW, Toplevel 
from mss import mss, tools



def full_screenshot(fn="img"):

    # Primary monitor screenshot
    filename = os.path.relpath(f'{fn}.png')

    with mss() as sct:
        sct.shot(mon=1, output=filename)

    return filename


def area_screenshot(sx, sy, ex, ey, fn="img"):

    try:
        os.mkdir("snaps")
    except:
        pass

    with mss() as sct:
        # The screen part to capture
        monitor = {"top": sy, "left": sx, "width": ex-sx, "height": ey-sy, "mon":1}
        filename = os.path.relpath("./snaps/" + fn + "-{top}x{left}_{width}x{height}.png".format(**monitor))

    # Grab the data
    sct_img = sct.grab(monitor)

    # Save to the picture file
    tools.to_png(sct_img.rgb, sct_img.size, output=filename)

    del sct


    return filename




class _Snap:

    def __init__(self, name="snap"):
    
        self.name = name
        self.snap = None

        self.window = Tk()
        #self.window = Toplevel(root)
    
        self.window.title("Snip picture")
        self.window.attributes('-fullscreen', True)  
    
        self.c = Canvas(self.window, cursor="cross")
        self.c.pack(expand=YES, fill=BOTH)

        fname = full_screenshot("temp")

        bg = PhotoImage(file=fname)
        self.c.create_image(0, 0, image=bg, anchor=NW)

        self.window.bind("<Escape>", self.quit_fullscreen)
        self.c.bind("<ButtonPress-1>", self.on_press)
        self.c.bind("<B1-Motion>", self.on_drag)
        self.c.bind("<ButtonRelease-1>", self.on_release)

        self.window.mainloop()
        #root.mainloop()

    
    def quit_fullscreen(self, event):
        self.window.attributes("-fullscreen", False)
            
    def clear_canvas(self):
    
        self.c.delete(self.rect)
        self.c.delete(self.d1)
        self.c.delete(self.d2)
    
        self.window.update()

    
    def on_press(self, event):
        #print("Pressed", event)
    
        self.sx = event.x
        self.sy = event.y
    
        self.rect = self.c.create_rectangle(self.sx, self.sy, self.sx, self.sy, width=2, fill="", dash=(3,5), outline="green3")
    
        self.d1 = self.c.create_line(self.sx, self.sy, self.sx, self.sy, width=1.2, fill="green2")
        self.d2 = self.c.create_line(self.sx, self.sy, self.sx, self.sy, width=1.2, fill="green2")
    
    
    def on_drag(self, event):
        #print("Draged", event)
        self.cx = event.x
        self.cy = event.y

        self.c.coords(self.rect, self.sx, self.sy, self.cx, self.cy)
        self.c.coords(self.d1, self.sx, self.sy, self.cx, self.cy)
        self.c.coords(self.d2, self.cx, self.sy, self.sx, self.cy)
    
    
    def on_release(self, event):
        #print("Released", event)
        self.ex = event.x
        self.ey = event.y
    
        self.clear_canvas()
        self.snap = area_screenshot(self.sx, self.sy, self.ex, self.ey, self.name)
        self.close_snip_window()
    
    
    def close_snip_window(self):
        os.remove("temp.png")
        self.window.withdraw()
        self.window.quit()
    
    
    

#Main function
def take_snap():
    
    obj = _Snap()

    cx = (obj.sx + obj.ex) / 2
    cy = (obj.sy + obj.ey) / 2

    data = {
        "sxy": (obj.sx, obj.sy,),
        "exy": (obj.ex, obj.ey,),
        "cxy": (cx, cy,),
        "snap": obj.snap
        }

    del obj

    return data



#take_snap()

我尝试使用 Toplevel() 函数,但没有成功。

4

1 回答 1

0

创建图像时,默认情况下它与主 Tk 窗口一起存储。由于您正在创建另一个 Tk 窗口,因此您需要指定图像窗口。

试试这个更新:

bg = PhotoImage(file=fname, master=self.window)  # link to child window
于 2020-10-18T14:37:58.253 回答