【问题标题】:There is an error although I followed documentation尽管我遵循了文档,但有一个错误
【发布时间】:2020-09-05 05:38:49
【问题描述】:
from PIL import Image
from tkinter import *

def wider():
    global photo,lbpic
    pic = photo.get()
    adj = Image.open(pic)
    width,height = adj.size
    new_pic = adj.resize((width*2,height))
    new_pic.save('Wider'+pic)
    lbpic['image'] = new_pic
    lbpic.image = new_pic

def taller():
    global photo,lbpic
    pic = photo.get()
    adj = Image.open(pic)
    width,height = adj.size
    new_pic = adj.resize((width,height*2))
    new_pic.save('Taller'+pic)
    lbpic['image'] = new_pic
    lbpic.image = new_pic

def rotateangle():
    global photo,lbpic,var
    pic = photo.get()
    adj = Image.open(pic)
    angle = var.get()
    result = adj.rotate(angle)
    result.save('rotated'+angle+pic)
    lbpic['image'] = result
    lbpic.image = result

def rotate():
    global photo,lbpic
    var = StringVar()
    var.set(90)
    rb1 = Radiobutton(win,text='90',variable=var,value=90,command=rotateangle)
    rb1.place(x=100,y=110)
    rb2 = Radiobutton(win,text='180',variable=var,value=180,command=rotateangle)
    rb2.place(x=100,y=140)
    rb3 = Radiobutton(win,text='270',variable=var,value=270,command=rotateangle)
    rb3.place(x=100,y=170)
    
    
win = Tk()
win.title('Photo adjust')
win.geometry('400x400')

lb = Label(win,text='Select a photo')
lb.place(x=100,y=20)

photo = StringVar()
en = Entry(win,textvariable=photo,width=30)
en.place(x=100,y=50)

btn = Button(win,text='Wider',command=wider)
btn.place(x=100,y=80)

btn2 = Button(win,text='Taller',command=taller)
btn2.place(x=150,y=80)

btnrotate = Button(win,text='Rotate',command=rotate)
btnrotate.place(x=200,y=80)

lbpic = Label(win,image='')
lbpic.place(x=150,y=200)

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python38\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "E:/Python/Python Projects Fun/photo_shop.py", line 7, in wider
    adj = Image.open(pic)
AttributeError: type object 'Image' has no attribute 'open'

对于这个程序,我想选择一张图片来改变按钮内的不同效果。但是我无法使用Image.open(pic) 打开图像,但我已经彻底检查了图像模块具有open 方法的文档。我遵循了文档,但我不明白问题出在哪里?还是版本问题?

【问题讨论】:

  • 您使用的是tkinter.Image 而不是PIL.Image,因为from tkinter import * 覆盖from PIL import Image。交换两个导入语句。您还需要将 PhotoImage 实例而不是 Image 分配给小部件。
  • 您的问题说明了为什么import * 不是首选。见PEP 8 -- Style Guide for Python Code

标签: python user-interface tkinter python-imaging-library


【解决方案1】:

这适用于 Windows::

解决方案 1

import tkinter as tk
from PIL import ImageTk, Image


root = tk.Tk()

myImage = ImageTk.PhotoImage(Image.open('test.png'))  # your image here

# you can do anything with that image object now.
# You can get all the common image formats (i used a png image)
# The PhotoImage object may not have attributes like PIL.Image 
# SO IN THAT CASE CHECK MY SECOND SOLUTION BELOW
#

tk.Label(root, image=myImage).pack()

root.mainloop()

原因:

根据您的import 语句(您使用过global imports - 也称为wildcard imports),来自tkinter 库的图像对象将覆盖您从PIL 导入的Image 对象。
这让interpreter 很难知道您是否真的使用过PIL.Imagetkinter.Image

***这就是为什么推荐使用像这样的import语句***

import tkinter as tk
from PIL import Image as Immmage # or whatever name you prefer
import tkinter.messagebox as msgb
from pyautogui import size

解决方案 2(根据您的需要)

如果您更改您的import style,您自己的代码甚至可以工作。

from PIL import Image as someThingElse  # your choice again
from tkinter import *   # again global import not recommended but only if you need so

def wider():
    global photo,lbpic
    pic = photo.get()
    adj = someThingElse.open(pic)
    width,height = adj.size
    new_pic = adj.resize((width*2,height))
    new_pic.save('Wider'+pic)
    lbpic['image'] = new_pic
    lbpic.image = new_pic

def taller():
    global photo,lbpic
    pic = photo.get()
    adj = someThingElse.open(pic)
    width,height = adj.size
    new_pic = adj.resize((width,height*2))
    new_pic.save('Taller'+pic)
    lbpic['image'] = new_pic
    lbpic.image = new_pic

def rotateangle():
    global photo,lbpic,var
    pic = photo.get()
    adj = someThingElse.open(pic)
    angle = var.get()
    result = adj.rotate(angle)
    result.save('rotated'+angle+pic)
    lbpic['image'] = result
    lbpic.image = result

def rotate():
    global photo,lbpic
    var = StringVar()
    var.set(90)
    rb1 = Radiobutton(win,text='90',variable=var,value=90,command=rotateangle)
    rb1.place(x=100,y=110)
    rb2 = Radiobutton(win,text='180',variable=var,value=180,command=rotateangle)
    rb2.place(x=100,y=140)
    rb3 = Radiobutton(win,text='270',variable=var,value=270,command=rotateangle)
    rb3.place(x=100,y=170)
    
    
win = Tk()
win.title('Photo adjust')
win.geometry('400x400')

lb = Label(win,text='Select a photo')
lb.place(x=100,y=20)

photo = StringVar()
en = Entry(win,textvariable=photo,width=30)
en.place(x=100,y=50)

btn = Button(win,text='Wider',command=wider)
btn.place(x=100,y=80)

btn2 = Button(win,text='Taller',command=taller)
btn2.place(x=150,y=80)

btnrotate = Button(win,text='Rotate',command=rotate)
btnrotate.place(x=200,y=80)

lbpic = Label(win,image='')
lbpic.place(x=150,y=200)

【讨论】:

  • 如果我想让图像文件调整为不同的效果,如调整大小、旋转和显示为标签,怎么样?
  • @Dom807 是的,你可以,上面的代码实际上适合标签内的图像(代码中的倒数第二行)。您也可以将其安装在 Button 上。另请参阅上面的编辑以了解更多信息。
  • 我现在可以了。非常感谢
  • 根据您的具体需求(使用您的代码)再次编辑了我的答案。也请仅在有助于解决问题的情况下接受答案:) 祝你好运
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
  • 1970-01-01
  • 2019-05-23
  • 2022-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多