Skip to content Skip to sidebar Skip to footer

Creating A Simple Gui Using Tkinter, And Having A Small Problem

One of the buttons i'm trying to create is not appearing correctly in the window. I've been trying to learn OOP, so my understanding of it is very basic right now, apologies in adv

Solution 1:

If you're trying to learn OOP, you're learning bad habits with this code.

Let's take a look at this code:

classSubmit(Button):def__init__(self, master):
        super().__init__()
        self.master = master
        Button(text='Submit', background='black', foreground='light green', highlightthickness=0,
               border=0)
        Button.pack(self)

First, because you inherit from Button, this class is aButton. You then call Button(text=...) which creates another button, so now you have two. If you're going to inherit from some other class, you don't need to create a second instance of that same class.

Also, these two lines are wrong:

super().__init__()
self.master = master

You need to pass master to the __init__ of the superclass. The master is more than just an attribute, it's an integral part of the definition of the widget. It affects how the widget will appear. It must be passed to the superclass in order for the widget to be properly initialized.

Also, this is slightly more subjective, but you should not be calling Button.pack(self) from within the definition of Submit. One of the main reasons for objects is to make reusable components. By having a widget call pack (or grid or place) on itself severely limits its re-usability. By calling pack inside Submit, it prevents you from using it or moving it to some other location in your UI which uses grid. That is an unnecessary constraint.

In my experience, the overall layout of a UI will change during development. What if you decide that you want to switch from pack to grid because you've designed to change the layout? The way you have written this code, you will have to modify every single class.

Instead, code that creates a widget should be responsible for calling pack, grid, or place. That means moving the call outside of the class and into the code that instantiates the class. This way, if you choose to use grid, or stay with pack but use some extra frames for organization, you only have to change the one function that creates each widget, rather than having to change every widget itself.

For example, the Submit button class should more look like this:

classSubmit(Button):def__init__(self, master):
        super().__init__(master)
        self.configure(text='Submit', background='black', foreground='light green',
                       highlightthickness=0, border=0)

Then, in the same code where it's created, that's where you call pack

submit = Submit(root)
...
submit.pack(...)

If you later decide to switch to grid, all you have to change is that last block of code.

Solution 2:

I'm not sure if there's just a single thing that's preventing the Submit button from being displayed, nor why you're deriving specialized widget subclasses that do nothing but hardcode some option settings into themselves — but, in general, you're not doing it correctly especially with respect to calling the superclass __init__() and configuring the instance inside each derived class' own __init__().

The reason this is a less than ideal way of doing things is because it's going to require different subclasses for every, say Button widget, your application needs — when all that's really required are instances of a single Button class with different values assigned to its attributes (which tkinter calls "options").

Subclassing should only be used when the actual code needs to be different. See the Definitions of subclass section of wikipedia article on Classes.

So, in my opinion you should instead just create instance of the stock tkinter widget and assign the options you want each to have when you create the instances. This is the way it's usually done and would be a lot simpler.

Anyway, here's how to do implement your approach correctly, which also happens to fix the Button not displaying issue:

import tkinter as tk
from tkinter import *
import tkinter.ttk as ttk


class Window(Frame):
    def __init__(self, master):
        super().__init__(master)
        self.master = master
        master.title('Learning Python')
        master.config(background='black')
        master.geometry('900x200')
        master.resizable(0, 0)


class Submit(Button):
    def __init__(self, master):
        super().__init__(master)
        self.master = master
        self.config(text='Submit', background='black', foreground='light green',
                    highlightthickness=0, border=0)
        self.pack()


class ProgressBar(ttk.Progressbar):
    def __init__(self, master):
        super().__init__(master)
        self.master = master
        self.config(orient='horizontal')
        self.pack(fill=tk.BOTH)


class PagesRead(Label):
    def __init__(self, master):
        super().__init__(master)
        self.master = master
        self.config(text='How many page(s) did you read?', background='black',
                    foreground='light green')
        self.pack()


class EntryBox(Entry):
    def __init__(self, master):
        super().__init__(master)
        self.master = master
        self.pack()


if __name__ == '__main__':
    root = tk.Tk()
    app = Window(root)
    bar = ProgressBar(root)
    pages = PagesRead(root)
    entry = EntryBox(root)
    submit = Submit(root)
    app.mainloop()

Screenshot

screenshot of tkinter app running and displaying all widgets

Post a Comment for "Creating A Simple Gui Using Tkinter, And Having A Small Problem"