0

In simply trying to work on organizing my code, I've found online that it seems to be best to put much of your code into classes when needed. So in doing that, I'd figure that I'll try to create a frame class with create_labels and create_buttons methods.

My goal is to be able to create 2 or more seperate frames that are similar in style (hence why I find it best to make a frame class). Then, using methods, create labels, buttons, and other widgets and allow them to move around with ease within their respective frames.

So here's my code:

import tkinter as tk
window = tk.Tk()


class MyFrame(tk.Frame):
    def __init__(self, parent, **kwargs):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        self.layout(**kwargs)

    def labels(self, text, **kwargs):
        tk.Label.__init__(self, text=text)
        self.layout(**kwargs)

    def buttons(self, text, command, **kwargs):
        tk.Button.__init__(self, text=text, command=command)
        self.layout(**kwargs)

    def layout(self, row=0, column=0, columnspan=None, row_weight=None, column_weight=None, color=None, sticky=None, ipadx=None, padx=None, ipady=None, pady=None):
        self.grid(row=row, column=column, columnspan=columnspan, sticky=sticky, ipadx=ipadx, padx=padx, ipady=ipady, pady=pady)
        self.grid_rowconfigure(row, weight=row_weight)
        self.grid_columnconfigure(column, weight=column_weight)
        self.config(bg=color)


frame_1 = MyFrame(window, row=0, column=0, sticky="news", color="pink")
frame_1.buttons("Btn_1/Frme_1", quit, row=0, column=0)
frame_1.buttons("Btn_2/Frme_1", quit, row=0, column=1)

frame_2 = MyFrame(window, row=1, column=0, sticky="news", color="green")
frame_2.buttons("Btn_1/Frme_2", quit, row=0, column=0)
frame_2.buttons("Btn_2/Frme_2", quit, row=0, column=1)

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

window.mainloop()

Now I think a problem of mine is during the __init__ method because there should be 2 frames and 2 buttons per frame. However, there's no errors which makes it harder to find out for sure of that's why only the latest buttons and frames exist. I don't even think it's a case of one frame or widget 'covering' another. I think the second frame/widgets seem to be overwriting the first frame/widgets.

Any help is appreciated.

Maz
  • 35
  • 8
  • It is true that you should put _much of your code into classes_. But how and what you put in them defines the ease of use ahead. For tkinter it makes sense to create classes as shown [here](https://stackoverflow.com/questions/17466561/best-way-to-structure-a-tkinter-application) – FrainBr33z3 Mar 10 '20 at 13:26

1 Answers1

1

The issue lies with your layout function. Both the frames are being grided on the row=0 and column=0, as you are not passing any specific row and column to the function. Hence, the overwriting of the frames can be seen.

Another issue (possible) in your code is that the frame_1 and frame_2 buttons do not belong to the Frame widget but to the root window

FrainBr33z3
  • 1,085
  • 1
  • 6
  • 12
  • Oh, I thought that the window could be considered another 'container' just like frames are. Also, I've rewritten the code to specify where the frames go but it still seems to overwrite. – Maz Mar 10 '20 at 11:10
  • And if I replace 'window' in the line where I assigned frame_1 and frame_2 with tk.Frame, I get this error: AttributeError: type object 'Frame' has no attribute 'tk' – Maz Mar 10 '20 at 11:16
  • considering your first problem, now the frames do not _overlap_ each other. This can be seen as clear regions marked in _pink_ and _green_ – FrainBr33z3 Mar 10 '20 at 11:27
  • My error. I meant to say that the BUTTONS still appear to overwrite. The buttons are created when I call the buttons method. And the parent is filled out as self. Since self is assigned to the particular frame I figured that that would work. – Maz Mar 10 '20 at 11:30
  • `self` in your case is a `.frame` object. You are not passing `self` as `master` to `Button.__init__`. Additionally, `Button.__init__` needs a Button instance of its own. So, currently your call to the `__init__` looks like: `(.frame, master=window, text=text, command=command)` – FrainBr33z3 Mar 10 '20 at 11:58
  • Ok I think I've almost got it. So how can I create an instance of ```Button.__init__```? – Maz Mar 10 '20 at 12:55
  • you cannot do it with your current way. Create `Buttons` outside of the `Frame` class, as `self` is reserved for a frame object in it. – FrainBr33z3 Mar 10 '20 at 13:24