Как я могу отобразить изображение в Python 3 с помощью tkinter/ttk?

Суть в том, что я делаю неправильно в следующем фрагменте кода?

    from tkinter import *
    from tkinter.ttk import *

    root = Tk()

    myButton = Button(root)
    myImage = PhotoImage(myButton, file='myPicture.gif')
    myButton.image = myImage
    myButton.configure(image=myImage)

    root.mainloop()

Сообщение об ошибке, которое я получаю от idle3, выглядит следующим образом:

    >>> 
    Traceback (most recent call last):
      File "/home/bob/Documents/Python/tkImageTest.py", line 9, in <module>
        myButton.configure(image=myImage)
      File "/usr/lib/python3.2/tkinter/__init__.py", line 1196, in configure
        return self._configure('configure', cnf, kw)
      File "/usr/lib/python3.2/tkinter/__init__.py", line 1187, in _configure
        self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
    TypeError: __str__ returned non-string (type Button)
    >>> 

Это сообщение об ошибке поставило меня в тупик, я просто не понимаю, что оно пытается сказать. Любые идеи?

Я также был бы признателен за предложения по изменению...


person Bobble    schedule 22.07.2012    source источник
comment
Кстати, я уже проверил эту ссылку effbot.org/tkinterbook/photoimage.htm - вы увидите мой фрагмент кода выглядит очень похоже!   -  person Bobble    schedule 22.07.2012
comment
Ошибка указывает на аргумент myButton, переданный в PhotoImage(). Я не верю, что PhotoImage() берет ссылку на объект виджета, поэтому это может быть причиной ошибки. Попробуйте эту строку без него, например myImage = PhotoImage(file='myPicture.gif')   -  person gary    schedule 22.07.2012
comment
@ Гэри, кажется, это так. Я был введен в заблуждение некоторыми документами (и некоторыми другими ошибками, которые я сгенерировал), думая, что PhotoImage нуждается в явной ссылке на корневое окно. После еще некоторого возни я обнаружил, что ссылка либо на корень, либо на саму кнопку может быть предоставлена ​​​​другим параметром конфигурации в конструкторе PhotoImage, подобным этому, PhotoImage(master=myButton, file='myFile.gif'), но так, как я это написал, это выглядит для Tkinter как имя, которое должно быть строкой, ofc.   -  person Bobble    schedule 23.07.2012
comment
Понятно. Превратил мой комментарий в ответ и добавил другую полезную информацию.   -  person gary    schedule 23.07.2012
comment
См. код, указанный в stackoverflow.com/questions/9142509/   -  person Harshan Gowda    schedule 09.03.2017


Ответы (2)


Ошибка указывает на аргумент myButton, переданный в PhotoImage. Как вы отметили в своем комментарии, PhotoImage обрабатывал объект виджета как строку (существует несколько вариантов строкового типа; см. список параметров PhotoImage здесь).

Ваш код будет работать, если вы реализуете эту строку без ссылки на объект myButton:

myImage = PhotoImage(file='myPicture.gif')

Я не уверен, что вам нужно изменить конструктор PhotoImage. Посмотрите документы PhotoImage, чтобы определить допустимые параметры (т. е. имена ресурсов) для этого класса. Цитирование файла справки:

Справка по классу PhotoImage в модуле tkinter:

класс Фотоизображение (изображение)

| Widget which can display colored images in GIF, PPM/PGM format.
|    
|  Method resolution order:  
|      PhotoImage  
|      Image  
|      builtins.object  
|    
|  Methods defined here:
|    
|  __getitem__(self, key)  
|      # XXX config  
|    
|  __init__(self, name=None, cnf={}, master=None, **kw)  
|      Create an image with NAME.
|
|      Valid resource names: data, format, file, gamma, height, palette, 
|      width.

К вашему сведению: самый простой способ получить доступ к документам из Python в командной строке или из IDLE:

from tkinter import PhotoImage
help(PhotoImage)

И, наконец, еще одна полезная ссылка на этот класс находится по адресу http://tkinter.unpythonic.net/wiki/PhotoImage.

person gary    schedule 22.07.2012
comment
Большое спасибо Гэри! Вы правы и в отношении «мастера». Это было пережитком некоторых экспериментов, которые я проводил с несколькими потоками (лучше не спрашивать!). - person Bobble; 24.07.2012
comment
@Bobble Кстати, если это ответило на вопрос, отметьте его как принятый ответ (похоже, это то, что вы можете сделать для некоторых ваших вопросов). - person gary; 12.09.2012

Я протестировал пример с Python 2.7.9, 3.2.5, 3.3.5, 3.4.3 в 32-битной и 64-битной версиях. (Вин 8.1 64бит)

Код работает.

(в python 3.4.3 64bit сначала появилось сообщение об ошибке.

Я полностью удалил 3.4.3, а затем переустановил.

Теперь пример работает и с 3.4.3 64 бит)

# basic code from >>
# http://tkinter.unpythonic.net/wiki/PhotoImage

# extra code -------------------------------------------------------------------------
from __future__ import print_function

try:
    import tkinter as tk
except:
    import Tkinter as tk

import sys
import platform

print ()
print ('python    ', sys.version)
print ('tkinter   ', tk.TkVersion)
print ()
print (platform.platform(),' ',platform.machine())
print ()


# basic code -------------------------------------------------------------------------

root = tk.Tk()

def create_button_with_scoped_image():
    # "w6.gif" >>
    # http://www.inf-schule.de/content/software/gui/entwicklung_tkinter/bilder/w6.gif
    img = tk.PhotoImage(file="w6.gif")  # reference PhotoImage in local variable
    button = tk.Button(root, image=img)
    # button.img = img  # store a reference to the image as an attribute of the widget
    button.image = img  # store a reference to the image as an attribute of the widget
    button.grid()

create_button_with_scoped_image()

tk.mainloop()
person frank.p    schedule 29.05.2015
comment
Вы уверены, что это ответ, а точнее ответ для python-3.x? - person Deduplicator; 29.05.2015
comment
Хороший ответ — это не только рабочий ответ, но и задокументированный. Нет смысла предоставлять код, если ОП его не понимает. Он/она должен что-то узнать из ответа, а не просто скопировать его, чтобы в следующий раз он/она задал тот же вопрос снова, только в другом контексте. - person ShellFish; 29.05.2015
comment
дело в том, что ответ от gary и Tkinter Wiki для меня не работает в Python 3.4.3 - person frank.p; 30.05.2015
comment
Я отредактировал свой пост; (в python 3.4.3 64bit у меня сначала появилось сообщение об ошибке. Я полностью удалил 3.4.3, а затем переустановил. Теперь пример работает и с 3.4.3 64 bit) - person frank.p; 30.05.2015