By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
438,428 Members | 1,340 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 438,428 IT Pros & Developers. It's quick & easy.

access properties of parent widget in Tkinter

P: n/a
I am trying to get & set the properties of a widget's parent widget.
What I have works, but seems like a long way around the block. First I
get the widget name using w.winfo_parent(), then i convert the name to a
reference using nametowidget().

self.nametowidget(event.widget.winfo_parent()).has Changed= True

It works, but I can't help but think I'm missing a more direct route. Am I?

Bill
Jul 19 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
William Gill wrote:
I am trying to get & set the properties of a widget's parent widget.
What I have works, but seems like a long way around the block. First I
get the widget name using w.winfo_parent(), then i convert the name to a
reference using nametowidget().

self.nametowidget(event.widget.winfo_parent()).has Changed= True


Personally I think it is bad design for a widget to assume anything about its enclosing environment. What about passing a StringVar or IntVar to the child widget and letting it work with that?

Kent
Jul 19 '05 #2

P: n/a
Kent Johnson wrote:
William Gill wrote:
I am trying to get & set the properties of a widget's parent widget.
What I have works, but seems like a long way around the block. First
I get the widget name using w.winfo_parent(), then i convert the name
to a reference using nametowidget().

self.nametowidget(event.widget.winfo_parent()).has Changed= True

Personally I think it is bad design for a widget to assume anything
about its enclosing environment. What about passing a StringVar or
IntVar to the child widget and letting it work with that?

Kent


Maybe I should clarify what I am doing and why, so that I can get a
better understanding of your replies.
The overall app is a gui editor for a database made up of several
related tables; one for basic info, one for their various phone numbers
(publish, contact, fax,cell, etc), one for various addresses (publish
,ship to, mail to, etc.), one for the services they subscribe to, etc.
The editor brings records from each of the various tables together in
one “record” for editing. Each table has an associated python/tkinter
class (widget) that displays the fields in a parent widget, and each
field is a child of the table widget. So “city” is a child of address,
is a child of client. If I change or add a phone number that db table
will need updating when I’m done, but the address table may not. I have
designed each table class with a hasChanged attribute, initialized to
False, if a child Entry widget changes I set has changed to True. When
I’m done the exit routine runs each table objects save routine, which
checks hasChanged to see if an update query needs to be run on that table.

Client
- basicData object (data from client table)
- company
- contact person
- notes
- phones object (data from phonenumber table)
- type (cell, fax, publish, etc)
- areaCode
- exchange
- base

If I change the area code in one record only the phonenumber table needs
to be updated, but since areaCode is a child of phones,
phones.hasChanged needs to be set to True by the areaCode entry widget.
Personally I think it is bad design for a widget to assume anything
about its enclosing environment. What about passing a StringVar or
IntVar to the child widget and letting it work with that?


This is not a criticism, but how is passing a known intVar or stringVar
any different than designing with the knowledge that an areaCode widget
can not exist except as a child of phonenumber? Besides, I need to
pass the state of areaCode (has it changed or not), not its value?
Bill

Jul 19 '05 #3

P: n/a
Kent Johnson wrote:
William Gill wrote:
I am trying to get & set the properties of a widget's parent widget.
What I have works, but seems like a long way around the block. First
I get the widget name using w.winfo_parent(), then i convert the name
to a reference using nametowidget().

self.nametowidget(event.widget.winfo_parent()).has Changed= True

Personally I think it is bad design for a widget to assume anything
about its enclosing environment. What about passing a StringVar or
IntVar to the child widget and letting it work with that?

Kent


A little more research into stringVar, and the stringVar.trace() method
may be one way to go. It may be simpler, or more convoluted having so
many stringVar objects. I'll do some experimenting, but I'm still open
to other ideas.

Bill
Jul 19 '05 #4

P: n/a
Kent Johnson wrote:
William Gill wrote:
I am trying to get & set the properties of a widget's parent widget.
What I have works, but seems like a long way around the block. First
I get the widget name using w.winfo_parent(), then i convert the name
to a reference using nametowidget().

self.nametowidget(event.widget.winfo_parent()).has Changed= True

Personally I think it is bad design for a widget to assume anything
about its enclosing environment. What about passing a StringVar or
IntVar to the child widget and letting it work with that?

Kent


I stumbled across the widget.master attribute. so

self.nametowidget(event.widget.winfo_parent()).has Changed = True

can be re-written as

self.master.hasChanged = True

I thought I was doing things the indirect way.

Thanks everyone for your help.

I'm still interested in if anyone thinks this is "bad practice", and why.

Bill
Jul 19 '05 #5

P: n/a
William Gill wrote:
Kent Johnson wrote:

If I change the area code in one record only the phonenumber table needs
to be updated, but since areaCode is a child of phones,
phones.hasChanged needs to be set to True by the areaCode entry widget.
One possibility is for the phones.hasChanged to poll the hasChanged attributes of its children. In other words, instead of propagating hasChanged up when a change occurs, poll the dependent widgets when you need to know.

Another way would be to pass a calllback to the child widget that it calls when it is changed, or to set up some kind of event mechanism. In Java I often set the parent to monitor property change events of the child.
> Personally I think it is bad design for a widget to assume anything
> about its enclosing environment. What about passing a StringVar or
> IntVar to the child widget and letting it work with that?
This is not a criticism, but how is passing a known intVar or stringVar
any different than designing with the knowledge that an areaCode widget
can not exist except as a child of phonenumber?


When you pass a stringVar to the child, it knows only what it is told, it is not assuming that some incantation on its parent will do the right thing. This has a direct effect on reusability of the child in other contexts. You may think you don't want to reuse the child, but it is very handy to be able to make a small test harness for a widget rather than firing up the whole application, navigating to the correct screen, etc. It is much harder to do this if the widget depends on its enclosing environment. And I find that if I design widgets for reuse, other uses tend to come up often enough to make it worth-while.

It's not that different from relying on any other global state. It makes code harder to understand, harder to test and harder to reuse.

More generally, IMO it is good practice to try to make acyclic dependency graphs between classes and modules, so if the parent depends on the child, the child shouldn't depend on the parent.
Besides, I need to
pass the state of areaCode (has it changed or not), not its value?
OK, I misunderstood your original post on that point.

Kent

Jul 19 '05 #6

P: n/a
Kent Johnson wrote:
William Gill wrote:
Kent Johnson wrote:

If I change the area code in one record only the phonenumber table
needs to be updated, but since areaCode is a child of phones,
phones.hasChanged needs to be set to True by the areaCode entry widget.

One possibility is for the phones.hasChanged to poll the hasChanged
attributes of its children. In other words, instead of propagating
hasChanged up when a change occurs, poll the dependent widgets when you
need to know.

Another way would be to pass a calllback to the child widget that it
calls when it is changed, or to set up some kind of event mechanism. In
Java I often set the parent to monitor property change events of the child.
> Personally I think it is bad design for a widget to assume anything
> about its enclosing environment. What about passing a StringVar or
> IntVar to the child widget and letting it work with that?


This is not a criticism, but how is passing a known intVar or
stringVar any different than designing with the knowledge that an
areaCode widget can not exist except as a child of phonenumber?

When you pass a stringVar to the child, it knows only what it is told,
it is not assuming that some incantation on its parent will do the right
thing. This has a direct effect on reusability of the child in other
contexts. You may think you don't want to reuse the child, but it is
very handy to be able to make a small test harness for a widget rather
than firing up the whole application, navigating to the correct screen,
etc. It is much harder to do this if the widget depends on its enclosing
environment. And I find that if I design widgets for reuse, other uses
tend to come up often enough to make it worth-while.

It's not that different from relying on any other global state. It makes
code harder to understand, harder to test and harder to reuse.

More generally, IMO it is good practice to try to make acyclic
dependency graphs between classes and modules, so if the parent depends
on the child, the child shouldn't depend on the parent.
Besides, I need to pass the state of areaCode (has it changed or not),
not its value?

OK, I misunderstood your original post on that point.

Kent

I will digest this some more, and see if the polling of child attributes
gets harder to follow than setting parent attributes.

In theory it makes sense to have the independence you discuss, in this
case it's hard to imaging needing the areaCode widget without the
(parent) phonenumber widget, but this is the exception. So your
suggestion makes more general sense.

By the way, my suspicion was right, self.master.hasChanged = True ,
provides direct access, but now I'm not sure that's the way to go.

Thanks,

Bill
Jul 19 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.