【问题标题】:Code organisation and instance of Class with arguments带参数的类的代码组织和实例
【发布时间】:2020-01-11 16:16:34
【问题描述】:

我正在使用 Tkinter 构建我的第一个应用程序,但我遇到了类实例。 我遵循了本教程https://pythonprogramming.net/change-show-new-frame-tkinter/,但仍然存在一些问题: - 如何将控制器作为不同类中 init 行的参数? - 我想在 classB 和相反的情况下创建 classA 的实例,但我在参数上弄错了! - 关于组织代码,我创建了 2 个类(每个框架一个)和写函数相关的好类,我应该将它们分成第 3 个类吗?最方便的方法是什么? 实际上代码正在运行,但我想在第二个窗口中添加一些设置工具! 我必须做什么才能修改 SettingsPage 类中的一些参数并在 StartPage 类中更新和使用它们?例如我想修改 ecartementlogo。

setp = SettingsPage(controller, StartPage) 给我 AttributeError: type object 'StartPage' has no attribute 'tk'

抱歉发布所有代码,但我不确定我可以删除示例中的哪些内容

import tkinter as tk
from PIL import Image, ImageDraw, ImageColor, ImageFont, ImageChops, ImageColor, ImageFont, ImageTk as PIL
import os
import utilitary as utilitary
import tkinter.ttk as ttk
from tkinter import filedialog
from configparser import ConfigParser

LARGE_FONT= ("Verdana", 12)
basewidth = 400
config = ConfigParser()
config.read('config.ini')


class DotaCasterKit(tk.Tk):

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.iconbitmap(self,default='icone.ico')
        tk.Tk.wm_title(self, "vs Creator")

        container = tk.Frame(self)

        container.pack(side="top", fill="both", expand = True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (StartPage, SettingsPage):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

        menu = tk.Menu(container)
        menu.config(background='#2B547E', fg='#2B547E')
        tk.Tk.config(self, menu=menu)
        file = tk.Menu(menu)
        file.add_command(label="Préférences", command=self.show_settings)
        file.add_command(label="Exit",command=quit)

        menu.add_cascade(label="File", menu=file)
        refresh = tk.Menu(menu)

        menu.add_cascade(label="Refresh", menu=refresh)

    def show_settings(self):

        frame = self.frames[SettingsPage]
        frame.tkraise()


class StartPage(tk.Frame):

    def choose_background(self):
        print(self.path_slogos)
        self.background_file = filedialog.askopenfilename(initialdir='C:/Users/.../VS')
        self.background = PIL.Image.open(self.background_file).convert('RGBA')
        self.background_name = os.path.basename(self.background_file)
        self.var1.set(self.background_name)

        self.miniature = self.background
        self.wpercent = (self.basewidth/float(self.miniature.size[0]))
        self.hsize = int((float(self.miniature.size[1])*float(self.wpercent)))
        self.miniature = self.miniature.resize((self.basewidth,self.hsize))
        self.miniature = PIL.PhotoImage(self.miniature)
        self.canvas.itemconfig(self.image_on_canvas, image =self.miniature)

    def choose_slogos_path(self):
        self.path_slogos = filedialog.askdirectory(initialdir='C:/Users/.../Logos')
        self.var2.set(os.path.basename(self.path_slogos))
        return self.path_slogos

    def create_list_logos(self):
        self.path_slogos = filedialog.askdirectory(initialdir='C:/Users/.../Logos')
        self.var2.set("Dossier : "+os.path.basename(self.path_slogos))
        self.files = []
        self.list_files_names =[]
        print(self.path_slogos)
        for r, d, f in os.walk(self.path_slogos):
            for file in f:
                if '.png' in file and 'background' not in file:
                    self.files.append(os.path.join(r, file))
                    name = os.path.basename(file)
                    name = name[:-4]
                    self.list_files_names.append(name)
        self.liste_1.config(values=self.list_files_names)
        self.liste_2.config(values=self.list_files_names)
        self.liste_1.current(0)
        self.liste_2.current(0)
        return self.list_files_names

    def create_img(self):
        self.composition = self.background
        self.ecartementlogo = 550
        rift_middle = ImageFont.truetype(os.path.join('C:/Users...rift/', 'fort_foundry_rift_bold.otf'), 150)
        text_middle = 'VS'
        text_match_format = self.entry_format_match.get()
        rift_match_format = ImageFont.truetype(os.path.join('C:/Users...rift/', 'fort_foundry_rift_bold.otf'), 60)
        rift_score = ImageFont.truetype(os.path.join('C:/Users...rift/', 'fort_foundry_rift_bold.otf'), 50)
        self.score_1 = self.entry_score__1.get()
        self.score_2 =  self.entry_score__2.get()
        self.1=self.liste_1.get()
        self.2=self.liste_2.get()
        self.logo_1 = PIL.Image.open(self.path_slogos+'/'+self.1+'.png').convert('RGBA')
        self.logo_2 = PIL.Image.open(self.path_slogos+'/'+self.2+'.png').convert('RGBA')
        #logo 1
        self.composition = utilitary.draw_image_advanced(self.composition, self.logo_1,
                                                      [960-int(self.ecartementlogo), 550],
                                                      [None, 300],
                                                      1)
        #logo 2
        self.composition = utilitary.draw_image_advanced(self.composition, self.logo_2,
                                                      [960+int(self.ecartementlogo), 550],
                                                      [None, 300],
                                                      1)

        image_draw = ImageDraw.Draw(self.composition)
        #insert text (VS + score)
        utilitary.draw_text_center_align(image_draw, [960, 450], text_middle, font=rift_middle, fill=utilitary.colors['white'])
        utilitary.draw_text_center_align(image_draw, [960, 600], text_match_format, font=rift_match_format, fill=utilitary.colors['white'])
        utilitary.draw_text_center_align(image_draw, [960-self.ecartementlogo, 700], self.score_1, font=rift_score, fill=utilitary.colors['light_red'])
        utilitary.draw_text_center_align(image_draw, [960+self.ecartementlogo, 700], self.score_2, font=rift_score, fill=utilitary.colors['light_red'])

        if self.var4.get()==0:
            pass
        if self.var4.get()==1:
            config.set('main', 'default_file_background', self.background_file)
            config.set('main', 'default_path_slogos', self.path_slogos)
            with open('config.ini', 'w') as f:
                config.write(f)
            print(self.background_file)
            print(self.path_slogos)
            print("settings saved")
        print("image created")

        self.miniature = self.composition
        self.wpercent = (self.basewidth/float(self.miniature.size[0]))
        self.hsize = int((float(self.miniature.size[1])*float(self.wpercent)))
        self.miniature = self.miniature.resize((self.basewidth,self.hsize))

        self.miniature = PIL.PhotoImage(self.miniature)
        self.canvas.itemconfig(self.image_on_canvas, image =self.miniature)


    def save_img(self):
        self.var5.set("Saved as " +self.1 + '_'+self.2+'.png')
        self.composition.save('C:/.../'+self.1 + '_'+self.2+'.png')

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        setp = SettingsPage(controller, StartPage)
### this line don't work ### wrong arguments
        self.background_file = config.get('main', 'default_file_background')
        self.path_slogos = config.get('main', 'default_path_slogos')
        self.group3 = tk.LabelFrame(self, text=" A & Score")
        self.group3.pack (side="left", padx=5, pady=5)
        self.group4 = tk.LabelFrame(self, text=" B & Score")
        self.group4.pack (side="right", padx=5, pady=5)

        self.liste_1 = ttk.Combobox(self.group3)
        self.liste_1.pack(side="top", padx=5, pady=5)

        self.liste_2 = ttk.Combobox(self.group4)
        self.liste_2.pack(side="top", padx=5, pady=5)
        self.liste_1, self.liste_2 = utilitary.initial_list_logos(self.path_slogos, self.liste_1, self.liste_2)

        self.liste_1.current(0)
        self.liste_2.current(0)
        self.group1 = tk.LabelFrame(self, text="Background")
        self.group1.pack (side="top", padx=5, pady=5)

        self.button_choose_background_file = tk.Button(self.group1, text="Choose Background")
        self.button_choose_background_file.config(command=self.choose_background)
        self.button_choose_background_file.pack (side="top", padx=5, pady=5)

        self.var1 = tk.StringVar()
        self.var1.set(os.path.basename(self.background_file))
        self.label_name_background_file = tk.Label(self.group1, textvariable=self.var1)
        self.label_name_background_file.pack (side="bottom", padx=5, pady=5)

        self.group2 = tk.LabelFrame(self, text="Logos s",labelanchor='ne')
        self.group2.pack (side="top", padx=5, pady=5)
        self.var2 = tk.StringVar()
        self.var2.set("Dossier : "+os.path.basename(self.path_slogos))
        self.label_path_slogo = tk.Label(self.group2, textvariable=self.var2)
        self.label_path_slogo.pack (side="bottom", padx=5, pady=5)

        self.button_list_logos = tk.Button(self.group2, text="Choose logos path")
        self.button_list_logos.config(command=self.create_list_logos)
        self.button_list_logos.pack (side="top", padx=5, pady=5)


        self.score_1 = tk.StringVar()
        self.score_1.set("")
        self.entry_score__1 = tk.Entry(self.group3,textvariable=self.score_1, width=5, justify='center')
        self.entry_score__1.pack(side="bottom", padx=5, pady=5)

        self.score_2 = tk.StringVar()
        self.score_2.set("")
        self.entry_score__2 = tk.Entry(self.group4,textvariable=self.score_2, width=5, justify='center')
        self.entry_score__2.pack(side="bottom", padx=5, pady=5)

        self.button_show = tk.Button(self, text="Show Image")
        self.button_show.config(command=self.create_img)
        self.button_show.pack (side="bottom", padx=5, pady=5)

        self.button_save_img = tk.Button(self, text="Save as image")
        self.button_save_img.config(command=self.save_img)
        self.button_save_img.pack (side="bottom", padx=5, pady=5)
        self.var5 = tk.StringVar ()
        self.var5.set('')
        self.label_name_save = tk.Label(self, textvariable =self.var5)
        self.label_name_save.pack (side="bottom", padx=5, pady=5)

        self.format_match = tk.StringVar()
        self.format_match.set("Format")
        self.entry_format_match = tk.Entry(self,textvariable=self.format_match, width=10, justify='center')
        self.entry_format_match.pack()

        self.var4 = tk.IntVar ()
        self.var4.set(0)
        self.button_save_settings = tk.Checkbutton(self, text="Save settings", variable = self.var4)
        self.button_save_settings.pack(side = "bottom")

        self.ecartementlogo = tk.IntVar ()
        self.var4.set(550)

        self.background=PIL.Image.open(self.background_file).convert('RGBA')
        self.basewidth = 400
        self.miniature = self.background
        self.wpercent = (self.basewidth/float(self.miniature.size[0]))
        self.hsize = int((float(self.miniature.size[1])*float(self.wpercent)))
        self.miniature = self.miniature.resize((self.basewidth,self.hsize))
        print(self.miniature.size)
        self.miniature = PIL.PhotoImage(self.miniature)
        self.canvas = tk.Canvas(self,width=400, height=225)
        self.image_on_canvas = self.canvas.create_image(0, 0, anchor="nw", image=self.miniature)
        self.canvas.pack()


class SettingsPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        startp = StartPage(controller, SettingsPage)
###this line work ### arguments are correct
        label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="Back to Edition Page",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()

        scale_x_logo_ = tk.Scale(self, orient='horizontal', from_=0, to=startp.background.size[0]/2,
                                                                resolution=10, length=350,
                                                                label='Placement horizontal logo', variable= startp.ecartementlogo)
        scale_x_logo_.pack()




app = DotaCasterKit()
app.geometry("%dx%d%+d%+d" % (850,620,100,100))
app.mainloop()

在 SettingsPage 类中使用的这一行是可以的: startp = StartPage(controller, SettingsPage) 我会说我需要写相反的,但是我的参数有错误(控制器,StartPage)但是这个 setp = SettingsPage(controller, StartPage) 不起作用(在 StartPage 类的 init 行中)

【问题讨论】:

  • 我正在尝试运行此代码以便找到您的问题,但它抱怨您正在尝试设置self.1,这是一个语法错误。在create_img 中,这还不到您的代码的一半。你能确定这实际上是正确的吗?
  • 您使用的是哪个版本的 Python?哪个版本的 Tkinter? (您可以通过tk.TclVersion 获得。)
  • 我建议您首先阅读此答案中的所有信息:stackoverflow.com/questions/7546050/…
  • @BrianOakley aut0wash 正在遵循基于该答案的教程。该教程实际上比答案包含更多信息,问题在于添加到该基本代码中的内容。

标签: python class user-interface tkinter


【解决方案1】:

问题就在这里:

class StartPage(tk.Frame):
    # ... Omitting irrelevant stuff
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        setp = SettingsPage(controller, StartPage) # Right here
        # ... More irrelevant stuff

您将 StartPage 传递给SettingsPage,而不是该类的实例。 SettingsPage 然后尝试将类解释为小部件,但类不是小部件并且没有tk 属性。

解决此问题的最佳方法是删除该行,因为您从不使用变量setpSettingsPage.__init__ 中的对应行也应该删除。

您还应该阅读@Brian Oakley 建议的链接。您的代码目前有很多问题。我已经修复了其中一个,他的链接应该可以帮助您修复更多。

【讨论】:

    猜你喜欢
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 2011-01-13
    • 1970-01-01
    • 2011-08-08
    • 2021-10-05
    相关资源
    最近更新 更多