Tkinter,PIL,图像未加载作物

时间:2016-05-01 20:58:10

标签: python tkinter python-imaging-library crop

我的代码应该在包含画布的topLevel窗口上加载图像,然后从该加载的图像中,我应该通过几个坐标在该图像中选择一个矩形。选择应该出现在主gui的画布上。

我访问了几个与我有同样问题的主题such as this one

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

1 个答案:

答案 0 :(得分:1)

测试您的代码,它按预期工作。您只是忘了将画布小部件放在主窗口中。添加crpImgCanvas.grid()或crImgCanvas.pack()对我有用。古德勒克!