Platytude
Platytude

Reputation: 127

tkinter: Pass Initialization Parameters to A Subclassed Custom Widget?

I've been trying to create a custom widget in tkinter, nothing too fancy, just a frame that holds an entry and two labels. I want the labels and the frame to be able to access StringVars of the parent application (ie. the textvariables for both of the labels, and the entry textvariable as well). I thought this should be fairly straightforward to do by passing these names through the initialization method as keyword args, but I'm running into trouble. Here's my code:

import tkinter as tk
import tkinter.ttk as ttk

class EntryFrame(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)

        self.title = kwargs.get('title')
        title = tk.Label(self, text=self.title)
        unit = tk.Label(self, text='(Unit)')
        self.entryVar = tk.StringVar()
        entry = tk.Entry(self, textvariable=self.entryVar)

        title.grid(row=0, column=0, sticky='es')
        unit.grid(row=0, column=1, sticky='ws')
        entry.grid(row=1, column=0, columnspan=2, padx=3, pady=3, sticky='n')

class TestApplication(tk.Frame):
    def __init__(self, master=None, *args, **kwargs):
        tk.Frame.__init__(self, master=None, *args, **kwargs)
        self.master=master
        self.grid(row=0, column=0)

        entryFrame  = EntryFrame(self, title='Title')
        entryFrame.grid(row=0, column=0)

root = tk.Tk()
Application = TestApplication(root)
root.mainloop()

I'm running into a problem where I can't actually pass anything else to my new widget, because it initializes with tk.Frame it seems to only want tk.frame attributes upon init. I can't actually give it args or kwargs.

If I try a different approach:

class EntryBox(self):
    def __init__(self, parent, *args, **kwargs):

        self.frame = tk.Frame(self)
        self.title = tk.Label(self, text='Title')
        self.unit = tk.Label(self, text='(Unit)')
        self.entryVar = tk.StringVar()
        entry = tk.Entry(self, textvariable=self.EntryVar)

        title.grid(row=0, column=0, sticky='es')
        unit.grid(row=0, column=1, sticky='es')
        entry.grid(row=1, column=0, columnspan=2, padx=3, pady=3, sticky='n')

The class throws errors about self not being defined.

EDIT:

A better example of code sample 2:

class EntryBox():
    def __init__(self, parent, *args, **kwargs):

        self.title=kwargs.pop('title')
        self.frame = tk.Frame(parent)
        self.frame.grid(row=0, column=0)
        self.title = tk.Label(self.frame, text=self.title)
        self.unit = tk.Label(self.frame, text='(Unit)')
        self.entryVar = tk.StringVar()


        self.entry = tk.Entry(self.frame)

        self.title.grid(row=0, column=0, sticky='es')
        self.unit.grid(row=0, column=1, sticky='es')
        self.entry.grid(row=1, column=0, columnspan=2, padx=3, pady=3, sticky='n')

Upvotes: 0

Views: 1551

Answers (1)

jasonharper
jasonharper

Reputation: 9622

Try something like:

def __init__(self, parent, title, **kwargs):        
    tk.Frame.__init__(self, parent, **kwargs)
    self.title = title   

In other words, avoid passing on your custom parameters to the superclass.

Or you could do self.title = kwargs.pop('title') BEFORE calling the superclass's __init__.

Your second code sample is simply confused - in class EntryBox(self):, what were you expecting 'self' to be?

Upvotes: 1

Related Questions