How can I shorten my Tkinter textbox code to avoid repetition?

49 views Asked by At

I'm writing a custom textbox to save my customer data to my database. I use Tkinter in python to create the UI, there are 5 textbox, each for different purpose. This is the code I use to create the textbox:

windows_a = Frame(root)
windows_a.pack(side=RIGHT, anchor=NE, padx=5, pady=30)
windows_a = Text(windows_a, width=16, height=38, font=("Consolas Bold", 11),
                 undo=True, tabs=25, insertbackground="white",
                 selectbackground="gray", selectforeground="yellow",
                 background="black", foreground="lime", wrap="none")
windows_a.pack()
windows_b = Frame(root)
windows_b.pack(side=RIGHT, anchor=NE, padx=0, pady=30)
windows_b = Text(windows_b, width=16, height=38, font=("Consolas Bold", 11),
                 undo=True, tabs=25, insertbackground="white",
                 selectbackground="gray", selectforeground="yellow",
                 background="black", foreground="lime", wrap="none")
windows_b.pack()
windows_c = Frame(root)
windows_c.pack(side=RIGHT, anchor=NE, padx=5, pady=30)
windows_c = Text(windows_c, width=30, height=38, font=("Consolas Bold", 11),
                 undo=True, tabs=25, insertbackground="white",
                 selectbackground="gray", selectforeground="yellow",
                 background="black", foreground="lime", wrap="none")
windows_c.pack()
username, password = Frame(root), Frame(root)
username.pack(side=TOP, anchor=NW, padx=5, pady=5)
username.place(x=5, y=35)
username = Text(username, width=10, height=1, font=("Consolas Bold", 11),
                undo=True, tabs=25, insertbackground="white",
                selectbackground="gray", selectforeground="yellow",
                background="black", foreground="lime")
username.pack()
password.pack(side=TOP, anchor=NW, padx=5, pady=0)
password.place(x=5, y=62)
password = Text(password, width=10, height=1, font=("Consolas Bold", 11),
                undo=True, tabs=25, insertbackground="white",
                selectbackground="gray", selectforeground="yellow",
                background="black", foreground="lime")
password.pack()

As you can see, apart from the position and size, the code is the same so I want to shorten it to make the code less repetitive. I tried to use grid but the different in their position and size make grid not a viable option.

Is there a way I can achieve the same output with less code, that isn't so repetitive?

2

There are 2 answers

1
SanguineL On BEST ANSWER

Following up on Henry's answer above: You can use loops to dynamically create CustomText objects.

windows_a, windows_b, windows_c = Frame(root), Frame(root), Frame(root)
widths = [16, 16, 30]
i = 0

for window in [windows_a, windows_b, windows_c]:
    window.pack(side=RIGHT, anchor=NE, padx=5, pady=30)
    CustomText(window, width = widths[i], height = 38).pack()
    i+= 1

username, password = Frame(root), Frame(root)

yi = 35

for frame in [username, password]:
    frame.place(x=5, y=yi)
    CustomText(frame, width=10, height=1).pack()
    yi = 64 # or yi += 29 if there eventually becomes more than two objects to loop through.
1
Henry On

You can wrap Text in your own class with default keyword arguments (kwargs). Then you can create instances of it like you did with Text but only specifying the arguments that change.

If you were to specify a different background colour, for example, this would override the defaults. If you want the default to always be enforced, change default_kwargs.update(kwargs) to kwargs.update(default_kwargs) and Text.__init__(self, *args, **default_kwargs) to Text.__init__(self, *args, **kwargs).

class CustomText(Text):
    def __init__(self, *args, **kwargs):
        default_kwargs = {
            "font": ("Consolas Bold", 11),
            "undo": True,
            "tabs": 25,
            "insertbackground": "white",
            "selectbackground": "gray",
            "selectforeground": "yellow",
            "background": "black",
            "foreground": "lime",
            "wrap": "none"
        }
        default_kwargs.update(kwargs)
        Text.__init__(self, *args, **default_kwargs)

windows_a = Frame(root)
windows_a.pack(side=RIGHT, anchor=NE, padx=5, pady=30)
windows_a = CustomText(windows_a, width=16, height=38)
windows_a.pack()
windows_b = Frame(root)
windows_b.pack(side=RIGHT, anchor=NE, padx=0, pady=30)
windows_b = CustomText(windows_b, width=16, height=38)
windows_b.pack()
windows_c = Frame(root)
windows_c.pack(side=RIGHT, anchor=NE, padx=5, pady=30)
windows_c = CustomText(windows_c, width=30, height=38)
windows_c.pack()
username, password = Frame(root), Frame(root)
username.pack(side=TOP, anchor=NW, padx=5, pady=5)
username.place(x=5, y=35)
username = CustomText(username, width=10, height=1)
username.pack()
password.pack(side=TOP, anchor=NW, padx=5, pady=0)
password.place(x=5, y=62)
password = CustomText(password, width=10, height=1)
password.pack()