Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Tkinter module test: widget class not inserted in application frame

16 views
Skip to first unread message

Rich Shepard

unread,
Jun 17, 2022, 12:27:28 PM6/17/22
to
I'm not seeing the error source in a small tkinter module I'm testing.

The module code:
-----------
import tkinter as tk
from tkinter import ttk

import common_classes as cc

class ConactNameInput(tk.Frame):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
# A dict to keep track of input widgets
self.inputs = {}

self.inputs['Last name'] = cc.LabelInput(
ContactNameInput, 'lname',
input_class = ttk.Entry,
input_var = tk.StringVar()
)
self.inputs['Last name'].grid(row = 0, column = 0)
#
self.inputs['First name'] = cc.LabelInput(
ContactNameInput, 'fname',
input_class = ttk.Entry,
input_var = tk.StringVar()
)
self.inputs['First name'].grid(row = 0, column = 1)

okay_button = tk.Button(self, text="OK",
command=self.ok)
okay_button.pack(side=tk.LEFT, padx=(20, 0), pady=(0, 20))

cancel_button = tk.Button(self, text="Cancel",
command=self.cancel)
cancel_button.pack(side=tk.RIGHT, padx=(0, 20), pady=(0, 20))

def okay_button(self):
pass

def cancel_button(self):
Quitter()

def get_last_name(self):
pass

def get_first_name(self):
pass


class NameApplication(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("Contact Name")
self.geometry("800x600")
self.resizable(width = False, height = False)
ContactNameInput(self).grid(row = 0, column = 0, sticky=('EWNS'))
self.columnconfigure(0, weight=1)

if __name__ == '__main__':
app = NameApplication()
app.mainloop()
----------

The python error traceback:
----------
Traceback (most recent call last):
File "contact_history_name_input.py", line 60, in <module>
app = NameApplication()
File "contact_history_name_input.py", line 55, in __init__
ContactNameInput(self).grid(row = 0, column = 0, sticky=('EWNS'))
File "contact_history_name_input.py", line 17, in __init__
input_var = tk.StringVar()
File "/home/rshepard/development/BusinessTracker/views/common_classes.py", line 46, in __init__
super().__init__(parent, **kwargs)
File "/usr/lib64/python3.7/tkinter/__init__.py", line 2744, in __init__
Widget.__init__(self, master, 'frame', cnf, {}, extra)
File "/usr/lib64/python3.7/tkinter/__init__.py", line 2292, in __init__
BaseWidget._setup(self, master, cnf)
File "/usr/lib64/python3.7/tkinter/__init__.py", line 2262, in _setup
self.tk = master.tk
AttributeError: type object 'ContactNameInput' has no attribute 'tk'
----------

I'm not correctly placing the NameInput class in the NameApplication frame.
What have I missed?

Rich

MRAB

unread,
Jun 17, 2022, 12:50:52 PM6/17/22
to
You haven't shown the code for common_classes.LabelInput, but I'm
guessing that the first argument should be the parent.

You're passing in the _class_ ConactNameInput, but I'm guessing that it
should be an _instance_ of that class, in this case, 'self'.

Rich Shepard

unread,
Jun 17, 2022, 1:06:36 PM6/17/22
to
On Fri, 17 Jun 2022, MRAB wrote:

> You haven't shown the code for common_classes.LabelInput, but I'm guessing
> that the first argument should be the parent.

Here's the LabelInput class:
class LabelInput(tk.Frame):
""" A widget containing a label and input together. """

def __init__(self, parent, label='', input_class=ttk.Entry,
input_var=None, input_args=None, label_args=None,
**kwargs):
super().__init__(parent, **kwargs)
label_args = label_args or {}
input_args = input_args or {}
self.variable = input_var,

if input_class in (ttk.Checkbutton, ttk.Button, ttk.Radiobutton):
input_args["text"] = label
input_args["variable"] = input_var
else:
self.label = ttk.Label(self, text=label, **label_args)
self.label.grid(row=0, column=0, sticky=(tk.W + tk.E))
input_args["textvariable"] = input_var

self.input = input_class(self, **input_args)
self.input.grid(row=1, column=0, sticky=(tk.W + tk.E))
self.columnconfigure(0, weight=1)
self.error = getattr(self.input, 'error', tk.StringVar())
self.error_label = ttk.Label(self, textvariable=self.error)
self.error_label.grid(row=2, column=0, sticky=(tk.W + tk.E))

def grid(self, sticky=(tk.E + tk.W), **kwargs):
super().grid(sticky=sticky, **kwargs)

def get(self):
try:
if self.variable:
return self.variable.get()
elif type(self.input) == tk.Text:
return self.input.get('1.0', tk.END)
else:
return self.input.get()
except (TypeError, tk.TclError):
# happens when numeric fields are empty.
return ''

def set(self, value, *args, **kwargs):
if type(self.variable) == tk.BooleanVar:
self.variable.set(bool(value))
elif self.variable:
self.variable.set(value, *args, **kwargs)
elif type(self.input) in (ttk.Checkbutton, ttk.Radiobutton):
if value:
self.input.select()
else:
self.input.deselect()
elif type(self.input) == tk.Text:
self.input.delete('1.0', tk.END)
self.input.insert('1.0', value)
else:
self.input.delete(0, tk.END)
self.input.insert(0, value)

> You're passing in the _class_ ConactNameInput, but I'm guessing that it
> should be an _instance_ of that class, in this case, 'self'.

Haven't I done this in the application class?
class NameApplication(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.title("Contact Name")
self.geometry("800x600")
self.resizable(width = False, height = False)
ContactNameInput(self).grid(row = 0, column = 0, sticky=('EWNS'))
self.columnconfigure(0, weight=1)

If not, where do I specify the instance of the ContactNameInput class?

Thanks,

Rich


--
Richard Shepard, Ph.D. The Environmental Issues Doctor
Applied Ecosystem Services, LLC
Troutdale, OR 97060 USA 503-667-4517 www[dot]appl-ecosys[dot]com

MRAB

unread,
Jun 17, 2022, 2:28:35 PM6/17/22
to
On 2022-06-17 18:06, Rich Shepard wrote:
> On Fri, 17 Jun 2022, MRAB wrote:
>
>> You haven't shown the code for common_classes.LabelInput, but I'm guessing
>> that the first argument should be the parent.
>
[snip]
>> You're passing in the _class_ ConactNameInput, but I'm guessing that it
>> should be an _instance_ of that class, in this case, 'self'.
>
> Haven't I done this in the application class?
> class NameApplication(tk.Tk):
> def __init__(self, *args, **kwargs):
> super().__init__(*args, **kwargs)
> self.title("Contact Name")
> self.geometry("800x600")
> self.resizable(width = False, height = False)
> ContactNameInput(self).grid(row = 0, column = 0, sticky=('EWNS'))
> self.columnconfigure(0, weight=1)
>
> If not, where do I specify the instance of the ContactNameInput class?
>
This:

self.inputs['Last name'] = cc.LabelInput(
ContactNameInput, 'lname',
input_class = ttk.Entry,
input_var = tk.StringVar()
)

should be this:

self.inputs['Last name'] = cc.LabelInput(
self, 'lname',
input_class = ttk.Entry,
input_var = tk.StringVar()
)

Also, this:

self.inputs['First name'] = cc.LabelInput(
ContactNameInput, 'fname',
input_class = ttk.Entry,
input_var = tk.StringVar()
)

should be this:

self.inputs['First name'] = cc.LabelInput(
self, 'fname',

Rich Shepard

unread,
Jun 17, 2022, 2:54:40 PM6/17/22
to
MRAB,

Ah! I must have misread Alan Moore's examples, then. I'll need to fix all my
views.

Thank you,

Rich

Dennis Lee Bieber

unread,
Jun 17, 2022, 8:46:12 PM6/17/22
to
On Fri, 17 Jun 2022 09:19:59 -0700 (PDT), Rich Shepard
<rshe...@appl-ecosys.com> declaimed the following:

>I'm not seeing the error source in a small tkinter module I'm testing.
>
>The module code:
>-----------
>import tkinter as tk
>from tkinter import ttk
>
>import common_classes as cc
>
>class ConactNameInput(tk.Frame):

Presuming this is a cut&paste of the actual code...

> ContactNameInput, 'lname',

> ContactNameInput, 'fname',


> ContactNameInput(self).grid(row = 0, column = 0, sticky=('EWNS'))

... please compare the spelling!



--
Wulfraed Dennis Lee Bieber AF6VN
wlf...@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/

Rich Shepard

unread,
Jun 17, 2022, 10:47:59 PM6/17/22
to
On Fri, 17 Jun 2022, Dennis Lee Bieber wrote:

>> ContactNameInput, 'lname',
>> ContactNameInput, 'fname',

This works if a tk.labelframe is where the widget is placed. In my case, as
MRAB taught me, the proper syntax is
self,'lname'...
self.'fname'...

Thanks, Dennis,

Rich

Peter J. Holzer

unread,
Jun 18, 2022, 4:16:07 AM6/18/22
to
On 2022-06-17 19:47:38 -0700, Rich Shepard wrote:
> On Fri, 17 Jun 2022, Dennis Lee Bieber wrote:
>
> > > ContactNameInput, 'lname',
> > > ContactNameInput, 'fname',
>
> This works if a tk.labelframe is where the widget is placed. In my case, as
> MRAB taught me, the proper syntax is
> self,'lname'...

There is a comma (U+002C) here ...

> self.'fname'...

And a dot (U+002E) here.

I don't think this is correct.

I would also recommend to always add a space after a comma.

hp

--
_ | Peter J. Holzer | Story must make more sense than reality.
|_|_) | |
| | | h...@hjp.at | -- Charles Stross, "Creative writing
__/ | http://www.hjp.at/ | challenge!"
signature.asc

Rich Shepard

unread,
Jun 18, 2022, 8:06:46 AM6/18/22
to
On Sat, 18 Jun 2022, Peter J. Holzer wrote:

> There is a comma (U+002C) here ...
> And a dot (U+002E) here.

That was a typo when I wrote the message. And I usually add a space after
commas and surrounding equal signs, all for easier reading.

Thank you,

Rich
0 new messages