gpt4 book ai didi

python - Python 中的重构(在 Eclipse 中提取新方法)

转载 作者:行者123 更新时间:2023-12-01 05:37:08 24 4
gpt4 key购买 nike

我正在尝试将一些 Python 2.7 代码重构为 Eclipse 中的新方法。当我在下面用注释标记的 block 上使用 Eclipse 的 Refactoring->Extract method 后,我的图像不再显示在 GUI 中:

from Tkinter import Tk, Button, W, E, N, S, Label, Frame

from PIL import Image, ImageTk

def myCallback():
pass

root = Tk()

# start refactor method here

root.geometry('400x400')
runButton = Button(root, text="Run",bg='green',
command=myCallback)
runButton.grid(row=2, column=0,
padx=10, pady=10)
quitButton = Button(root, text="Quit",
command=root.quit)
quitButton.grid(row=2, column=1,
padx=10, pady=10)

frame1 = Frame(width=200, height=200)
frame1.grid(row=1, column=0, columnspan=1, rowspan=1,
sticky=W+E+N+S, padx=10, pady=10)
image1 = Image.open("C:/Users/me/Pictures/house.jpg")
size = 64,64
image1.thumbnail(size, Image.ANTIALIAS)
photo1 = ImageTk.PhotoImage(image1)
label1 = Label(image=photo1)
label1.grid(row=0, column=10, columnspan=1, rowspan=1,
sticky=N+E, padx=10, pady=10)

# end refactor method here

root.mainloop()

有人可以解释为什么图像消失并提出一个解决方案,以便我可以在不丢失图像的情况下进行重构吗?

重构后:

from Tkinter import Tk, Button, W, E, N, S, Label, Frame

from PIL import Image, ImageTk

def extractedMethod(root):
root.geometry('400x400')
runButton = Button(root, text="Run", bg='green', command=myCallback)
runButton.grid(row=2, column=0, padx=10, pady=10)
quitButton = Button(root, text="Quit",
command=root.quit)
quitButton.grid(row=2, column=1, padx=10, pady=10)
frame1 = Frame(width=200, height=200)
frame1.grid(row=1, column=0, columnspan=1, rowspan=1, sticky=W + E + N + S, padx=10, pady=10)
image1 = Image.open("C:/Users/me/Pictures/house.jpg")
size = 64, 64
image1.thumbnail(size, Image.ANTIALIAS)
photo1 = ImageTk.PhotoImage(image1)
label1 = Label(image=photo1)
label1.grid(row=0, column=10, columnspan=1, rowspan=1, sticky=N + E, padx=10, pady=10)

def myCallback():
pass

root = Tk()
extractedMethod(root)

root.mainloop()

谢谢。

最佳答案

问题在于您过早释放 PhotoImage 对象。

the docs解释一下:

You must keep a reference to the image object in your Python program, either by storing it in a global variable, or by attaching it to another object.

Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget.

To avoid this, the program must keep an extra reference to the image object. A simple way to do this is to assign the image to a widget attribute, like this:

label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()

您可能认为将其作为 image 参数传递给 Label 构造函数可以使其保持事件状态。但事实并非如此; Label 实际上并不保留对 PhotoImage 对象本身的引用,它只是在 mainloop 之后运行的 Tcl 代码中的实际标签构造开始这样做。 (它类似于弱引用,但不是有意或明确的引用,如果有帮助的话。)

因此,快速而肮脏的解决方案是将其添加到 extractedMethod 的顶部:

global photo1

...或在 label1 = Label(image=photo1) 行之后添加此内容:

label1.photo = photo1
<小时/>

避免这种情况的更好方法是使用面向对象设计而不是平面过程设计,这样您就有一些合理的对象来拥有所有引用。

即使是简单的版本,如these examples所示会起作用:

class Foo(object):
def __init__(self, root):
# put the code from extractedMethod here,
# but prefix every local variable with self,
# and do the same for myCallback.
def myCallback(self):
pass

但你可能最好采用真正的面向对象设计,其中你的对象实际上代表某些东西,如the official examples :

class MyFrame(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.create_widgets()
def myCallback(self):
pass
def create_widgets(self):
# put the code from extractedMethod here,
# again prefixing things with self

关于python - Python 中的重构(在 Eclipse 中提取新方法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18665973/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com