Tkinter画布不显示

3 投票
2 回答
9394 浏览
提问于 2025-04-15 19:02

我正在尝试学习一些Python和Tkinter。下面的示例代码是想在屏幕上显示两个窗口、几个按钮,还有一个带有图片和一些线条的画布。

窗口和按钮都显示得很好,但我看不到画布上的图片和线条。我希望能得到一些帮助,弄清楚怎么才能让我的画布显示出来。

from Tkinter import *
import Image, ImageTk

class App:

    def __init__(self, master):

    def scrollWheelClicked(event):
        print "Wheel wheeled"

    frame = Frame(master)
    frame.pack()
    self.button = Button(frame, text = "QUIT", fg="red", command=frame.quit)
    self.button.pack(side=LEFT)

    self.hi_there = Button(frame, text="Hello", command=self.say_hi)
    self.hi_there.pack(side=LEFT)

    top = Toplevel()
    canvas = Canvas(master=top, width=600, height=600)

    image = Image.open("c:\lena.jpg")
    photo = ImageTk.PhotoImage(image)
    item = canvas.create_image(0, 0, image=photo)

    canvas.create_line(0, 0, 200, 100)
    canvas.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
    canvas.create_rectangle(50, 25, 150, 75, fill="blue")

    canvas.pack

    testBtn = Button(top, text = "test button")
    testBtn.pack()

def say_hi(self):
    print "hi there everyone!"

root = Tk()
app = App(root)
root.mainloop()

2 个回答

7

我解决了这个问题:

self.photo = ImageTk.PhotoImage(image)
self.item = canvas.create_image(0, 0, image=self.photo)

你需要把ImageTk的实例保存在某个地方,否则当你的App.__init__()方法执行完毕后,它就会被垃圾回收掉,这样画布就无法显示它了。(Tkinter并不会自动保存这个图片的引用。)

保持这个引用的一种方法是把它存储在“self.photo”里,或者用一个叫'photo'的变量,或者像大多数程序员对常量变量(那些不会改变的变量,比如'TEN = 10')那样,写成'PHOTO = PhotoImage(...)'。至于为什么这样做……我也不知道。导入'gc'模块(Python 3自带的垃圾回收模块)并运行gc.disable()是没用的。(如果你想试试,可以看看这个链接:https://docs.python.org/3/library/gc.html

4

在调用画布对象的 pack 方法时,你需要加上括号。否则,你只是提到这个函数,而不是在真正调用它。

举个例子:

canvas.pack()

再举一个例子:

>>>def hello():
...    print "hello world"
...    return

>>>hello 会返回这个函数的引用(function hello at 0x....)

>>>hello() 实际上是调用了 hello 这个函数

撰写回答