HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Instantiating widgets

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
instantiatingwidgetsstackoverflow

Problem

In my Tkinter projects I almost always end up with __init__() methods that look like this:

import tkinter as tk
from .common import ConfigPageFrame

class SystemInformationPageFrame(ConfigPageFrame):
    def __init__(self, parent, callback_dict):
        super().__init__(parent)

        self.columnconfigure(0, weight=1)
        self.rowconfigure(0, weight=1)

        self.button_text = "Refresh"
        self.button_callback = callback_dict['btn_refresh']

        self.lbl_sys_desc_text = "System description:"
        self.lbl_model_text = "Model:"
        self.lbl_serial_text = "Serial number:"
        self.lbl_mac_text = "Burned in MAC:"
        self.lbl_soft_ver_text = "Software version:"
        self.lbl_os_text = "Operating system:"
        self.lbl_net_chip_text = "Network processing device:"

        self.btn_refresh = tk.Button(self, text=button_text,
                                command=button_callback)
        self.btn_refresh.grid(column=0, row=10, columnspan=2)

        self.lbl_sys_desc = tk.Label(self, text=lbl_sys_desc_text, anchor=tk.E)
        self.lbl_model = tk.Label(self, text=lbl_model_text, anchor=tk.E)
        self.lbl_serial = tk.Label(self, text=lbl_serial_text, anchor=tk.E)
        self.lbl_mac = tk.Label(self, text=lbl_mac_text, anchor=tk.E)
        self.lbl_soft_ver = tk.Label(self, text=lbl_soft_ver_text, anchor=tk.E)
        self.lbl_os = tk.Label(self, text=lbl_os_text, anchor=tk.E)
        self.lbl_net_chip = tk.Label(self, text=lbl_net_chip_text, anchor=tk.E)

        self.lbl_sys_desc.grid(column=0, row=0, sticky=tk.E)
        self.lbl_model.grid(column=0, row=1, sticky=tk.E)
        self.lbl_serial.grid(column=0, row=2, sticky=tk.E)
        self.lbl_mac.grid(column=0, row=3, sticky=tk.E)
        self.lbl_soft_ver.grid(column=0, row=4, sticky=tk.E)
        self.lbl_os.grid(column=0, row=5, sticky=tk.E)
        self.lbl_net_chip.grid(column=0, row=6, sticky=tk.E)


This sample is a GUI class from quite a large project, s

Solution

The answer really depends on what you're building. For example, if you're building a grid of labels and entry widgets then a simple data structure and loop is all you need. For example:

fields = [
    {"id": "sys_desc", "label": "System description", "default_value": ""},
    {"id": "model", "label": "Model", "default_value": ""},
    ...
] 
self.labels = {} 
self.entries = {}     
for field in fields:
    label = tk.Label(self, field["label"], ...)
    entry = tk.Entry(self, ...)
    entry.insert("end", field["default_value"])

    self.label[field["id"]] = label
    self.entry[field["id"] = entry

self.label["sys_desc"].grid(...)
self.entry["sys_desc"].grid(...)
...


Another solution is to create a helper class or helper function so that your code looks something like this:

self.add_widget(self, "sys_desc", "System Description", "default value...", row=1)
self.add_widget(self, "model", "Model", "default model", row=2)
self.add_widget(self, "serial", "Serial Number", "default serial value", row=3)
...


Or with classes:

self.sys_desc = LabelEntry(self, "System Description", ...)
self.model = LabelEntry(self, "Model", ...)
self.serial = LabelEntry(self, ...)
...


There is no single answer for all layouts. Complex layouts require complex code, simple layouts can be built with simple code. The bottom line is to look for patterns, and make helpers to help reduce repetitive code.

Code Snippets

fields = [
    {"id": "sys_desc", "label": "System description", "default_value": ""},
    {"id": "model", "label": "Model", "default_value": ""},
    ...
] 
self.labels = {} 
self.entries = {}     
for field in fields:
    label = tk.Label(self, field["label"], ...)
    entry = tk.Entry(self, ...)
    entry.insert("end", field["default_value"])

    self.label[field["id"]] = label
    self.entry[field["id"] = entry

self.label["sys_desc"].grid(...)
self.entry["sys_desc"].grid(...)
...
self.add_widget(self, "sys_desc", "System Description", "default value...", row=1)
self.add_widget(self, "model", "Model", "default model", row=2)
self.add_widget(self, "serial", "Serial Number", "default serial value", row=3)
...
self.sys_desc = LabelEntry(self, "System Description", ...)
self.model = LabelEntry(self, "Model", ...)
self.serial = LabelEntry(self, ...)
...

Context

StackExchange Code Review Q#142066, answer score: 3

Revisions (0)

No revisions yet.