Tkinter,PIL,图像未加载作物

Tkinter, PIL, Image not loading with crop

我的代码应该在包含 canvas 的顶级 window 上加载图像,然后从该加载的图像,我应该 select 通过几个坐标一个矩形在那个图像中。 selection 应该出现在主 gui 的 canvas.

我访问了几个可能与我有相同问题的主题,

  1. 我尝试通过将 imgLoadedimgCropLoaded 设为全局变量来实现所提供的解决方案(请参阅下面的代码),但这并没有解决我的问题,
  2. 注意在我的代码中,变量 idCrop = cropCanvas.create_image(0,0,anchor='nw',image=imgCropLoaded) 在调试期间取值 1,所以真正唯一的问题是图像不显示,
  3. 如果您想测试我的代码:运行它,然后加载 JPEG/.jpg 图像。载入后,您可以尝试点击它(在第二个 window 上)并拖动一个矩形来制作 selection,左上角和右下角的坐标将显示在控制台。

这是我的代码(我还是 python 和 tkInter 的新手)

from _functools import partial
from tkinter import Tk, Menu, Canvas, Frame, Toplevel
from tkinter.filedialog import askopenfilename

from PIL import ImageTk, Image


#Variables globales
xSelectHG=0
ySelectHG=0

xSelectBD=0
ySelectBD=0

#last Rectangle Id
idRectangle = 0

#Image files references from PhotoImage
imgLoaded = 0
imgCropLoaded = 0

# Functions
def deleteRectangle(canvas,id):
    canvas.delete(id)
    return

def startSelectPortion(event):
    global xSelectHG
    xSelectHG = event.x

    global ySelectHG    
    ySelectHG = event.y
    #print("[X,Y]Hg=",xSelectHG, ySelectHG)
    return
def stopSelectPortion(imgFile,cropCanvas,canvas,event):

    #Delete previous rectangle
    global idRectangle
    deleteRectangle(canvas, idRectangle)


    global xSelectBD
    xSelectBD = event.x

    global ySelectBD    
    ySelectBD = event.y
    #print("[X,Y]BD=",xSelectBD, ySelectBD)
    #print("[X,Y]BD=",xSelectBD, ySelectBD)

    startCrop(imgFile,cropCanvas,canvas)
    return

def startCrop(imgFile, cropCanvas, canvas):
    #Cropping an image
    #Crop box:
    #global xSelectHG, ySelectHG, xSelectBD, ySelectBD
    print("[X,Y]Hg=",xSelectHG, ySelectHG)
    print("[X,Y]BD=",xSelectBD, ySelectBD)
    cropBox = (xSelectHG,ySelectHG,xSelectBD,ySelectBD)
    imgCrop = imgFile.crop(cropBox)
    global imgCropLoaded
    imgCropLoaded = ImageTk.PhotoImage(imgCrop)
    #Keeping a reference of the loaded image
    cropCanvas.image = imgCropLoaded
    cropCanvas.config(height=imgCrop.size[0],width=imgCrop.size[1])

    #This idCrop seems to be 1 during debuggin, so the image loads successfully, but it doesn't get displayed.
    idCrop = cropCanvas.create_image(0,0,anchor='nw',image=imgCropLoaded)
    global idRectangle
    idRectangle=canvas.create_rectangle(xSelectHG,ySelectHG,xSelectBD,ySelectBD)
    canvas.update()
    cropCanvas.update()
    return

def openImage(topLevel,canvas, cropCanvas):
    imgFormats = [("JPEG","*.jpg")]
    imgName = askopenfilename(filetypes=imgFormats,title="Please choose an image of JPEG format")
    imgFile = Image.open(imgName)
    global imgLoaded
    imgLoaded = ImageTk.PhotoImage(imgFile)
    canvas.config(height=imgFile.size[0], width=imgFile.size[1])
    #Keeping a reference of the loaded image
    canvas.img = imgLoaded
    canvas.create_image(0,0,anchor='nw',image=imgLoaded)
    canvas.grid(row=0,columns=1)
    canvas.bind('<Button-1>',partial(startSelectPortion))
    canvas.bind('<ButtonRelease-1>',partial(stopSelectPortion, imgFile, cropCanvas, canvas))

    return

def quit():
    gui.destroy()
    return
gui = Tk()

#How to make this top level appear only when I click the button?
imgTopLevel = Toplevel(gui)

imgCanvas = Canvas(imgTopLevel, height=100, width=100)
crpImgCanvas = Canvas(gui,height=100,width=100)

menubar = Menu(gui)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Files", menu=filemenu)
filemenu.add_command(label="Open", command=partial(openImage, imgTopLevel,imgCanvas,crpImgCanvas))
menubar.add_separator()
menubar.add_command(label="Quit", command=partial(quit))

gui.config(menu=menubar)
gui.mainloop()

已测试您的代码,它按预期工作。您只是忘记将 canvas 小部件放在主 window 中。添加 crpImgCanvas.grid() 或 crImgCanvas.pack() 对我有用。祝你好运!