Tkinter: Class Instance issue when StringVar is Named
All,
I am a little baffled by this one and hope that someone out there can explain what is going on.
The example is little convoluted but it serves the point of illustrating the problem I am seeing in my app. I have three classes that extend Tkinter.Frame; A, B and X. B contains an instance of A and a variable (a label) whose value is dependent on the state of an Option Menu in A. X has multiple instances of B. When I set name='opt_var' in the line below (from Class A), b1 and b2 within X act as if they are the same instance of B.
self.opt_var = StringVar(name='opt_var')
However, when I remove name='opt_var' from the StringVar declaration, I get the expected (i.e. independent) behavior of two separate instances.
What confuses me even further is I do a comparison of the two instances of B using "b1 is b2" - which I understand is supposed to check if two variables point to the same object - and I get True which is unexpected as b1 and b2 are instantiated separatly.
Any insight into what is going is appreciated.
from Tkinter import *
import collections
# A simple class with an Option Menu
class A(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.opt_dict = collections.OrderedDict()
self.opt_dict['Option A'] = 0
self.opt_dict['Option B'] = 1
keys = self.opt_dict.keys()
self.opt_var = StringVar(name='opt_var')
self.opt_var.set(keys[0])
opt_om = OptionMenu(self, self.opt_var, *keys).pack()
# A simple class with a Label whose value is determined by Class A's option
class B(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.lbl = Label(self, text='What did you choose?')
self.lbl.pack()
self.a = A(self)
self.a.pack()
# set a 'trace' on a's StringVar with a local callback
self.a.opt_var.trace('w', self.myfunction)
def myfunction(self, *args):
# this seems a little convoluted here but in the app where I
# came across this issue, there are more than just two choices
optB = bool(self.a.opt_dict[self.a.opt_var.get()])
if (optB):
self.lbl.config(text='Option B')
else:
self.lbl.config(text='Option A')
# a simple class with multiple instances of B
class X(Frame):
def __init__(self, master):
Frame.__init__(self, master)
b1 = B(self).pack()
b2 = B(self).pack()
print(b1 is b2)
root = Tk()
frame = X(root).pack()
root.mainloop()
tkinter callback trace
add a comment |
All,
I am a little baffled by this one and hope that someone out there can explain what is going on.
The example is little convoluted but it serves the point of illustrating the problem I am seeing in my app. I have three classes that extend Tkinter.Frame; A, B and X. B contains an instance of A and a variable (a label) whose value is dependent on the state of an Option Menu in A. X has multiple instances of B. When I set name='opt_var' in the line below (from Class A), b1 and b2 within X act as if they are the same instance of B.
self.opt_var = StringVar(name='opt_var')
However, when I remove name='opt_var' from the StringVar declaration, I get the expected (i.e. independent) behavior of two separate instances.
What confuses me even further is I do a comparison of the two instances of B using "b1 is b2" - which I understand is supposed to check if two variables point to the same object - and I get True which is unexpected as b1 and b2 are instantiated separatly.
Any insight into what is going is appreciated.
from Tkinter import *
import collections
# A simple class with an Option Menu
class A(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.opt_dict = collections.OrderedDict()
self.opt_dict['Option A'] = 0
self.opt_dict['Option B'] = 1
keys = self.opt_dict.keys()
self.opt_var = StringVar(name='opt_var')
self.opt_var.set(keys[0])
opt_om = OptionMenu(self, self.opt_var, *keys).pack()
# A simple class with a Label whose value is determined by Class A's option
class B(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.lbl = Label(self, text='What did you choose?')
self.lbl.pack()
self.a = A(self)
self.a.pack()
# set a 'trace' on a's StringVar with a local callback
self.a.opt_var.trace('w', self.myfunction)
def myfunction(self, *args):
# this seems a little convoluted here but in the app where I
# came across this issue, there are more than just two choices
optB = bool(self.a.opt_dict[self.a.opt_var.get()])
if (optB):
self.lbl.config(text='Option B')
else:
self.lbl.config(text='Option A')
# a simple class with multiple instances of B
class X(Frame):
def __init__(self, master):
Frame.__init__(self, master)
b1 = B(self).pack()
b2 = B(self).pack()
print(b1 is b2)
root = Tk()
frame = X(root).pack()
root.mainloop()
tkinter callback trace
add a comment |
All,
I am a little baffled by this one and hope that someone out there can explain what is going on.
The example is little convoluted but it serves the point of illustrating the problem I am seeing in my app. I have three classes that extend Tkinter.Frame; A, B and X. B contains an instance of A and a variable (a label) whose value is dependent on the state of an Option Menu in A. X has multiple instances of B. When I set name='opt_var' in the line below (from Class A), b1 and b2 within X act as if they are the same instance of B.
self.opt_var = StringVar(name='opt_var')
However, when I remove name='opt_var' from the StringVar declaration, I get the expected (i.e. independent) behavior of two separate instances.
What confuses me even further is I do a comparison of the two instances of B using "b1 is b2" - which I understand is supposed to check if two variables point to the same object - and I get True which is unexpected as b1 and b2 are instantiated separatly.
Any insight into what is going is appreciated.
from Tkinter import *
import collections
# A simple class with an Option Menu
class A(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.opt_dict = collections.OrderedDict()
self.opt_dict['Option A'] = 0
self.opt_dict['Option B'] = 1
keys = self.opt_dict.keys()
self.opt_var = StringVar(name='opt_var')
self.opt_var.set(keys[0])
opt_om = OptionMenu(self, self.opt_var, *keys).pack()
# A simple class with a Label whose value is determined by Class A's option
class B(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.lbl = Label(self, text='What did you choose?')
self.lbl.pack()
self.a = A(self)
self.a.pack()
# set a 'trace' on a's StringVar with a local callback
self.a.opt_var.trace('w', self.myfunction)
def myfunction(self, *args):
# this seems a little convoluted here but in the app where I
# came across this issue, there are more than just two choices
optB = bool(self.a.opt_dict[self.a.opt_var.get()])
if (optB):
self.lbl.config(text='Option B')
else:
self.lbl.config(text='Option A')
# a simple class with multiple instances of B
class X(Frame):
def __init__(self, master):
Frame.__init__(self, master)
b1 = B(self).pack()
b2 = B(self).pack()
print(b1 is b2)
root = Tk()
frame = X(root).pack()
root.mainloop()
tkinter callback trace
All,
I am a little baffled by this one and hope that someone out there can explain what is going on.
The example is little convoluted but it serves the point of illustrating the problem I am seeing in my app. I have three classes that extend Tkinter.Frame; A, B and X. B contains an instance of A and a variable (a label) whose value is dependent on the state of an Option Menu in A. X has multiple instances of B. When I set name='opt_var' in the line below (from Class A), b1 and b2 within X act as if they are the same instance of B.
self.opt_var = StringVar(name='opt_var')
However, when I remove name='opt_var' from the StringVar declaration, I get the expected (i.e. independent) behavior of two separate instances.
What confuses me even further is I do a comparison of the two instances of B using "b1 is b2" - which I understand is supposed to check if two variables point to the same object - and I get True which is unexpected as b1 and b2 are instantiated separatly.
Any insight into what is going is appreciated.
from Tkinter import *
import collections
# A simple class with an Option Menu
class A(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.opt_dict = collections.OrderedDict()
self.opt_dict['Option A'] = 0
self.opt_dict['Option B'] = 1
keys = self.opt_dict.keys()
self.opt_var = StringVar(name='opt_var')
self.opt_var.set(keys[0])
opt_om = OptionMenu(self, self.opt_var, *keys).pack()
# A simple class with a Label whose value is determined by Class A's option
class B(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.lbl = Label(self, text='What did you choose?')
self.lbl.pack()
self.a = A(self)
self.a.pack()
# set a 'trace' on a's StringVar with a local callback
self.a.opt_var.trace('w', self.myfunction)
def myfunction(self, *args):
# this seems a little convoluted here but in the app where I
# came across this issue, there are more than just two choices
optB = bool(self.a.opt_dict[self.a.opt_var.get()])
if (optB):
self.lbl.config(text='Option B')
else:
self.lbl.config(text='Option A')
# a simple class with multiple instances of B
class X(Frame):
def __init__(self, master):
Frame.__init__(self, master)
b1 = B(self).pack()
b2 = B(self).pack()
print(b1 is b2)
root = Tk()
frame = X(root).pack()
root.mainloop()
tkinter callback trace
tkinter callback trace
asked Dec 29 '18 at 2:52
user3525060user3525060
32
32
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Tkinter is a thin wrapper around an embedded Tcl interpreter. This interpreter knows nothing about python namespaces.
When you create an instance of StringVar
, this creates a new global variable in that Tcl interpreter. Normally a unique variable name is picked by Tkinter. When you explicitly give it a name, that becomes the name of the global variable. If you create multiple instances of StringVar
and give each the same name, they will all be tied to the same single Tcl variable.
The solution is simple: each instance of your class needs to create an instance of a StringVar
with a unique name.
Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.
– user3525060
Dec 30 '18 at 7:13
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53966312%2ftkinter-class-instance-issue-when-stringvar-is-named%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Tkinter is a thin wrapper around an embedded Tcl interpreter. This interpreter knows nothing about python namespaces.
When you create an instance of StringVar
, this creates a new global variable in that Tcl interpreter. Normally a unique variable name is picked by Tkinter. When you explicitly give it a name, that becomes the name of the global variable. If you create multiple instances of StringVar
and give each the same name, they will all be tied to the same single Tcl variable.
The solution is simple: each instance of your class needs to create an instance of a StringVar
with a unique name.
Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.
– user3525060
Dec 30 '18 at 7:13
add a comment |
Tkinter is a thin wrapper around an embedded Tcl interpreter. This interpreter knows nothing about python namespaces.
When you create an instance of StringVar
, this creates a new global variable in that Tcl interpreter. Normally a unique variable name is picked by Tkinter. When you explicitly give it a name, that becomes the name of the global variable. If you create multiple instances of StringVar
and give each the same name, they will all be tied to the same single Tcl variable.
The solution is simple: each instance of your class needs to create an instance of a StringVar
with a unique name.
Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.
– user3525060
Dec 30 '18 at 7:13
add a comment |
Tkinter is a thin wrapper around an embedded Tcl interpreter. This interpreter knows nothing about python namespaces.
When you create an instance of StringVar
, this creates a new global variable in that Tcl interpreter. Normally a unique variable name is picked by Tkinter. When you explicitly give it a name, that becomes the name of the global variable. If you create multiple instances of StringVar
and give each the same name, they will all be tied to the same single Tcl variable.
The solution is simple: each instance of your class needs to create an instance of a StringVar
with a unique name.
Tkinter is a thin wrapper around an embedded Tcl interpreter. This interpreter knows nothing about python namespaces.
When you create an instance of StringVar
, this creates a new global variable in that Tcl interpreter. Normally a unique variable name is picked by Tkinter. When you explicitly give it a name, that becomes the name of the global variable. If you create multiple instances of StringVar
and give each the same name, they will all be tied to the same single Tcl variable.
The solution is simple: each instance of your class needs to create an instance of a StringVar
with a unique name.
edited Dec 29 '18 at 4:39
answered Dec 29 '18 at 4:16
Bryan OakleyBryan Oakley
214k21255418
214k21255418
Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.
– user3525060
Dec 30 '18 at 7:13
add a comment |
Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.
– user3525060
Dec 30 '18 at 7:13
Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.
– user3525060
Dec 30 '18 at 7:13
Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.
– user3525060
Dec 30 '18 at 7:13
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53966312%2ftkinter-class-instance-issue-when-stringvar-is-named%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown