0

I'm building my first app with Tkinter and I'm stuck with instance of class. I followed this tutorial https://pythonprogramming.net/change-show-new-frame-tkinter/ but some questions remain : - how does mean controller as argument for the init line in the differents class ? - I would like to create instance of classA in classB and inversely but I'm getting wrong with arguments ! - About organisation code, I created 2 class (one for each frame) and writting function related in the good one, should I split them in a 3rd class ? What is the most convenient way ? Actualy the code is running but I would like to add some setup tools in the 2nd window ! What do I must do to can modify some parameters in the SettingsPage Class and update and use them in the StartPage class ? For example I would like to modify ecartementlogo.

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

Sorry for posting all the code but I not sure about what can I remove for the example

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()

This line used in the SettingsPage Class is ok : startp = StartPage(controller, SettingsPage) I would say I need to write the reverse one but I having error with arguments (controller, StartPage) BUT this one setp = SettingsPage(controller, StartPage) don't work (in the init line of StartPage Class)

aut0wash
  • 45
  • 8
  • I'm trying to run this code so I can find your problem, and it complains that you are trying to set `self.1`, which is a syntax error. This is a bit less than halfway down your code, in `create_img`. Can you make sure this is actually correct? – Hiatsu Sep 09 '19 at 22:22
  • Which version of Python are you using? Which version of Tkinter? (You can get that by `tk.TclVersion`.) – Hiatsu Sep 09 '19 at 22:32
  • 2
    I suggest you start by reading all of the information in this answer: https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter – Bryan Oakley Sep 09 '19 at 22:59
  • @BrianOakley aut0wash is following a tutorial based on that answer. The tutorial actually has some more information than the answer does, and the issue is with what has been added to that base code. – Hiatsu Sep 09 '19 at 23:03

1 Answers1

0

The issue is here:

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

You are passing the class StartPage to the SettingsPage, rather than an instance of that class. SettingsPage then tries to interpret the class as a widget, but a class is not a widget and does not have a tk attribute.

The best way to fix this is to remove that line, since you never use the variable setp. The corresponding line in SettingsPage.__init__ should also be removed.

You should also read the link suggested by @Brian Oakley. Your code currently has many issues. I have fixed one of them, and his link should help you fix more.

Hiatsu
  • 157
  • 1
  • 6