将 class 实例化到 Python 中的函数时如何传递参数?
How to pass arguments when instantiating a class to a function in Python?
我已尝试仅描述和记录每个 class 必要的内容,希望您能帮助我,我正在尝试 实例化 class
Show_image
需要两个参数,
图像列表的两个索引,如果你能指导我,如果我想做的事情是可能的,我将不胜感激。谢谢。
此 class 调整图像大小
from tkinter importante *
from PIL import Image, ImageTk
class Array(Frame):
def __init__(self, master, path, *args):
Frame.__init__(self, master, *args) self.image = Image.open(path)
self.img_copy = self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self, image=self.background_image)
self.background.pack(fill='both', expand=True)
self.background.bind('<Configure>', self._resize_image)
def _resize_image(self, event):
self.image = self.img_copy .resize ((self.master .winfo_width(), self.master .winfo_height()))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image=self.background_image)
基础class对照
class Interface(Frame):
def __init__(self, master, *args):
Frame.__init__(self, master, *args)
self.path_lst = ['11.png','22.png','33.png','44.png'] # change/add paths
self._frame_1 = None
self._open_1 = False
self.button1 = Button(self, text='pack 1',
command= lambda:self.windows(Show_image))
self.button1 .pack()
def windows(self, var_1):
if not self._open_1:
self.top1 = Toplevel(self.master)
self.top1 .geometry('200x200')
container = var_1(self.top1)
if self._frame_1 is not None:
self._frame_1 .destroy()
self._frame_1 = container
self._frame_1 .pack()
self._open_1 = True
self.top1.protocol ('WM_DELETE_WINDOW', lambda: self.closed(1))
def closed(self, number):
if number == 1:
self.top1. destroy()
self._open_1 = False
这个class应该画两个instance,两个image,但是不知道怎么传<index_1>
and <index_2>
绑定参数 <lambda>
函数。
class Show_image(Frame):
def __init__(self, index_1, index_2, *args, **kwargs):
Frame.__init__(self, *args, **kwargs)
self.img = Array(self, self.master.path_lst[index_1])
self.img .grid(column=0, row=0)
self.img2 = Array(self, self.master.path_lst[index_2])
self.img2 .grid(column=0, row=1)
root = Tk()
frm = Interface(root)
frm .pack()
root.mainloop()
另外,请问图片的初始化路径是否正确。谢谢。
如果我理解你将不得不使用嵌套 lambdas
command=lambda:self.windows(lambda:Show_image(index1, index2))
但我看到 windows
运行带有参数 top
的函数,因此它在 lambda
中也需要它
command=lambda:self.windows( lambda top:Show_image(index1, index2, top))
编辑:
具有其他更改的完整工作代码。
我发送 master
作为第一个值, path_lst
作为最后一个值,我不需要使用 self.master.pack_lst
我更改了一些 pack()
、grid()
并添加了 grid_rowconfigure()
,以便在 window 更改大小时正确调整图像大小。
我用 os.listdir()
创建了 path_lst
。它使用 sys.argv
从命令行 (python script.py path_to_images
) 获取 folder
或使用 os.getcwd()
获取 Current Working Directory
作为 folder
我按照建议将 ShowImage
改名为 PEP8
- CamelCaseNames
for 类.
我不确定它是否建议将 noun
用于 类(如名词 ImageViewer
而不是动词 ShowImage
)和 verb
用于函数(比如动词 show_window
而不是名词 windows
)但我跳过了它。也许是书中的建议'Clean Code' by Robert C. Martin (also known as Uncle Bob)
PEP 8 -- Style Guide for Python Code
import os # os.path.join(), os.listdir()
import sys # sys.argv
#from tkinter import * # PEP8: `import *` is not preferred
import tkinter as tk
from PIL import Image, ImageTk
# --- constants --- # PEP8: `UPPER_CASE_NAMES
#FOLDER = '/home/furas/test'
# --- classes --- # PEP8: `CamelCaseNames`
class Array(tk.Frame):
def __init__(self, master, path, *args):
super().__init__(master, *args) # in Python 3 you can use `super()` without `self`
self.image = Image.open(path)
self.img_copy = self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = tk.Label(self, image=self.background_image)
self.background.pack(fill='both', expand=True)
self.background.bind('<Configure>', self._resize_image)
def _resize_image(self, event):
self.image = self.img_copy.resize((self.master.winfo_width(), self.master.winfo_height()//2))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image=self.background_image)
class Interface(tk.Frame):
def __init__(self, master, folder, *args):
super().__init__(master, *args)
self.folder = folder
#self.path_lst = ['11.png','22.png','33.png','44.png'] # change/add paths
self.path_lst = [os.path.join(self.folder, name) for name in os.listdir(self.folder) if name.lower().endswith(('.png', '.jpg', '.gif'))] # change/add paths
self._frame_1 = None
self._open_1 = False
index_1 = 0
index_2 = 1
self.button1 = tk.Button(self, text='pack 1',
command=lambda:self.windows(lambda top:ShowImage(top, index_1, index_2, self.path_lst)))
self.button1.pack()
def windows(self, var_1):
if not self._open_1:
self.top1 = tk.Toplevel(self.master)
self.top1.geometry('200x200')
container = var_1(self.top1)
if self._frame_1 is not None:
self._frame_1.destroy()
self._frame_1 = container
self._frame_1.pack(fill='both', expand=True)
self._open_1 = True
self.top1.protocol('WM_DELETE_WINDOW', lambda: self.closed(1))
def closed(self, number):
if number == 1:
self.top1.destroy()
self._open_1 = False
class ShowImage(tk.Frame):
def __init__(self, master, index_1, index_2, path_lst, *args, **kwargs):
super().__init__(master, *args, **kwargs)
if len(path_lst) > index_1:
self.img = Array(self, path_lst[index_1])
self.img.grid(column=0, row=0, sticky='news')
if len(path_lst) > index_2:
self.img2 = Array(self, path_lst[index_2])
self.img2.grid(column=0, row=1, sticky='news')
# column 0 will use full width
self.grid_columnconfigure(0, weight=1)
# row 0 will use 1/2 height AND row 1 will use 1/2 height
self.grid_rowconfigure(0, weight=1)
self.grid_rowconfigure(1, weight=1)
# --- functions --- # PEP8: `lower_case_names`
# empty
# --- main ---
if len(sys.argv) > 1:
folder = sys.argv[1]
else:
folder = os.getcwd()
#folder = FOLDER
root = tk.Tk()
frm = Interface(root, folder)
frm.pack()
root.mainloop()
顺便说一句:
因为 window 必须显示两个图像,所以我将 Array
中的高度除以 2 (self.master.winfo_height()//2
) 以适应 window 中的两个 rows/images。
我已尝试仅描述和记录每个 class 必要的内容,希望您能帮助我,我正在尝试 实例化 class
Show_image
需要两个参数,
图像列表的两个索引,如果你能指导我,如果我想做的事情是可能的,我将不胜感激。谢谢。
此 class 调整图像大小
from tkinter importante *
from PIL import Image, ImageTk
class Array(Frame):
def __init__(self, master, path, *args):
Frame.__init__(self, master, *args) self.image = Image.open(path)
self.img_copy = self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self, image=self.background_image)
self.background.pack(fill='both', expand=True)
self.background.bind('<Configure>', self._resize_image)
def _resize_image(self, event):
self.image = self.img_copy .resize ((self.master .winfo_width(), self.master .winfo_height()))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image=self.background_image)
基础class对照
class Interface(Frame):
def __init__(self, master, *args):
Frame.__init__(self, master, *args)
self.path_lst = ['11.png','22.png','33.png','44.png'] # change/add paths
self._frame_1 = None
self._open_1 = False
self.button1 = Button(self, text='pack 1',
command= lambda:self.windows(Show_image))
self.button1 .pack()
def windows(self, var_1):
if not self._open_1:
self.top1 = Toplevel(self.master)
self.top1 .geometry('200x200')
container = var_1(self.top1)
if self._frame_1 is not None:
self._frame_1 .destroy()
self._frame_1 = container
self._frame_1 .pack()
self._open_1 = True
self.top1.protocol ('WM_DELETE_WINDOW', lambda: self.closed(1))
def closed(self, number):
if number == 1:
self.top1. destroy()
self._open_1 = False
这个class应该画两个instance,两个image,但是不知道怎么传<index_1>
and <index_2>
绑定参数 <lambda>
函数。
class Show_image(Frame):
def __init__(self, index_1, index_2, *args, **kwargs):
Frame.__init__(self, *args, **kwargs)
self.img = Array(self, self.master.path_lst[index_1])
self.img .grid(column=0, row=0)
self.img2 = Array(self, self.master.path_lst[index_2])
self.img2 .grid(column=0, row=1)
root = Tk()
frm = Interface(root)
frm .pack()
root.mainloop()
另外,请问图片的初始化路径是否正确。谢谢。
如果我理解你将不得不使用嵌套 lambdas
command=lambda:self.windows(lambda:Show_image(index1, index2))
但我看到 windows
运行带有参数 top
的函数,因此它在 lambda
command=lambda:self.windows( lambda top:Show_image(index1, index2, top))
编辑:
具有其他更改的完整工作代码。
我发送 master
作为第一个值, path_lst
作为最后一个值,我不需要使用 self.master.pack_lst
我更改了一些 pack()
、grid()
并添加了 grid_rowconfigure()
,以便在 window 更改大小时正确调整图像大小。
我用 os.listdir()
创建了 path_lst
。它使用 sys.argv
从命令行 (python script.py path_to_images
) 获取 folder
或使用 os.getcwd()
获取 Current Working Directory
作为 folder
我按照建议将 ShowImage
改名为 PEP8
- CamelCaseNames
for 类.
我不确定它是否建议将 noun
用于 类(如名词 ImageViewer
而不是动词 ShowImage
)和 verb
用于函数(比如动词 show_window
而不是名词 windows
)但我跳过了它。也许是书中的建议'Clean Code' by Robert C. Martin (also known as Uncle Bob)
PEP 8 -- Style Guide for Python Code
import os # os.path.join(), os.listdir()
import sys # sys.argv
#from tkinter import * # PEP8: `import *` is not preferred
import tkinter as tk
from PIL import Image, ImageTk
# --- constants --- # PEP8: `UPPER_CASE_NAMES
#FOLDER = '/home/furas/test'
# --- classes --- # PEP8: `CamelCaseNames`
class Array(tk.Frame):
def __init__(self, master, path, *args):
super().__init__(master, *args) # in Python 3 you can use `super()` without `self`
self.image = Image.open(path)
self.img_copy = self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = tk.Label(self, image=self.background_image)
self.background.pack(fill='both', expand=True)
self.background.bind('<Configure>', self._resize_image)
def _resize_image(self, event):
self.image = self.img_copy.resize((self.master.winfo_width(), self.master.winfo_height()//2))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image=self.background_image)
class Interface(tk.Frame):
def __init__(self, master, folder, *args):
super().__init__(master, *args)
self.folder = folder
#self.path_lst = ['11.png','22.png','33.png','44.png'] # change/add paths
self.path_lst = [os.path.join(self.folder, name) for name in os.listdir(self.folder) if name.lower().endswith(('.png', '.jpg', '.gif'))] # change/add paths
self._frame_1 = None
self._open_1 = False
index_1 = 0
index_2 = 1
self.button1 = tk.Button(self, text='pack 1',
command=lambda:self.windows(lambda top:ShowImage(top, index_1, index_2, self.path_lst)))
self.button1.pack()
def windows(self, var_1):
if not self._open_1:
self.top1 = tk.Toplevel(self.master)
self.top1.geometry('200x200')
container = var_1(self.top1)
if self._frame_1 is not None:
self._frame_1.destroy()
self._frame_1 = container
self._frame_1.pack(fill='both', expand=True)
self._open_1 = True
self.top1.protocol('WM_DELETE_WINDOW', lambda: self.closed(1))
def closed(self, number):
if number == 1:
self.top1.destroy()
self._open_1 = False
class ShowImage(tk.Frame):
def __init__(self, master, index_1, index_2, path_lst, *args, **kwargs):
super().__init__(master, *args, **kwargs)
if len(path_lst) > index_1:
self.img = Array(self, path_lst[index_1])
self.img.grid(column=0, row=0, sticky='news')
if len(path_lst) > index_2:
self.img2 = Array(self, path_lst[index_2])
self.img2.grid(column=0, row=1, sticky='news')
# column 0 will use full width
self.grid_columnconfigure(0, weight=1)
# row 0 will use 1/2 height AND row 1 will use 1/2 height
self.grid_rowconfigure(0, weight=1)
self.grid_rowconfigure(1, weight=1)
# --- functions --- # PEP8: `lower_case_names`
# empty
# --- main ---
if len(sys.argv) > 1:
folder = sys.argv[1]
else:
folder = os.getcwd()
#folder = FOLDER
root = tk.Tk()
frm = Interface(root, folder)
frm.pack()
root.mainloop()
顺便说一句:
因为 window 必须显示两个图像,所以我将 Array
中的高度除以 2 (self.master.winfo_height()//2
) 以适应 window 中的两个 rows/images。