Tkinter: Class Instance issue when StringVar is Named












0















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()









share|improve this question



























    0















    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()









    share|improve this question

























      0












      0








      0








      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()









      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 29 '18 at 2:52









      user3525060user3525060

      32




      32
























          1 Answer
          1






          active

          oldest

          votes


















          1














          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.






          share|improve this answer


























          • Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.

            – user3525060
            Dec 30 '18 at 7:13











          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          1














          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.






          share|improve this answer


























          • Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.

            – user3525060
            Dec 30 '18 at 7:13
















          1














          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.






          share|improve this answer


























          • Thanks for the explanation. It seems odd the Tkinter does not comply with basic object oriented principals.

            – user3525060
            Dec 30 '18 at 7:13














          1












          1








          1







          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.






          share|improve this answer















          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.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          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



















          • 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


















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          Monofisismo

          Angular Downloading a file using contenturl with Basic Authentication

          Olmecas