Tkinter.Button subclass needs tuple constructor argument

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • TMS
    New Member
    • Sep 2006
    • 119

    #16
    ok, well, part of the problem is that I'm not calling KeyButton anywhere. So, I added KeyButton().mai nloop() to just below root=Tk() and this is the error message I get:

    Traceback (most recent call last):
    File "C:\Python25\bu ttonTest.pyw", line 52, in <module>
    KeyButton().mai nloop()
    TypeError: __init__() takes exactly 3 arguments (1 given)

    meaning that I didn't call it right. So, with your help, I'm getting closer, I'm sure... but still needs help. Thank you for helping me with this!

    Comment

    • bartonc
      Recognized Expert Expert
      • Sep 2006
      • 6478

      #17
      I ran this. Some stuff you have in there, you'll have to work out. Mostly getting quotes right, I think (but I don't really see what you're trying to do with the [].
      Code:
      from Tkinter import *
      buttonData = \
      (
      ## ( ('~\n`', 1), ('!\n1', 1), ([url="http://'@\n2'"]'@\n2'[/url], 1), ('#\n3', 1), ('$\n4', 1),
      ## ('%\n5', 1), ('^\n6', 1), ('&\n7', 1), ('*\n8', 1), ('(\n9', 1),
      ## (')\n0', 1), ('_\n-', 1), ('+\n=', 1), ('Backspace', 2)),
      
       (('Tab', 2), ('Q', 1), ('W', 1), ('E', 1), ('R', 1), ('T', 1),
       ('Y', 1), ('U', 1), ('I', 1), ('O', 1), ('P', 1), ('{\n[', 1),
       ('}\n]', 1), ('|\n\\', 1)),
      
       (('CapsLock', 2), ('A', 1), ('S', 1), ('D', 1), ('F', 1), ('G', 1),
       ('H', 1), ('J', 1), ('K', 1), ('L', 1), (':\n;', 1), ('"\n\'', 1),
       ('Enter', 2)),
      
       (('Shift', 2), ('Z', 1), ('X', 1), ('C', 1), ('V', 1), ('B', 1),
       ('N', 1), ('M', 1), ('<\n,', 1), ('>\n.', 1), ('?\n/', 1), ('Shift', 3)),
      
       (('Ctrl', 2), ('Alt', 2), ('Space', 7), ('Alt', 2), ('Ctrl', 2)),
      )
      
      
      class KeyButton(Button):
          def __init__(self, parent, label_state):
              label = label_state[0]
              self.btnStates = label.split()
              self.state = label_state[1]
              Button.__init__(self, parent, text=label, command=self.DoAction)
      
      
          def DoAction(self):
              try:
                  print self.btnStates[self.state]
              except IndexError:
                  print "No such state"
          def SetState(self, state):
              self.state = state
      
      
      if __name__ == "__main__":
          root = Tk()
      
          btnList = [] # an empty list
          for rowNum, rowTuple in enumerate(buttonData):
              for colNum, constTuple in enumerate(rowTuple):
                  keyButton=KeyButton(root, constTuple) #I put this in... NEED INNER MOST DATA!
                  keyButton.grid(row=rowNum, column=colNum)
                  btnList.append(keyButton) # a linerar list of all the buttons.
      
      
          root.mainloop()

      Comment

      • bartonc
        Recognized Expert Expert
        • Sep 2006
        • 6478

        #18
        Originally posted by bartonc
        I ran this. Some stuff you have in there, you'll have to work out. Mostly getting quotes right, I think (but I don't really see what you're trying to do with the [].
        Code:
        from Tkinter import *
        buttonData = \
        (
        ## ( ('~\n`', 1), ('!\n1', 1), ([url="http://'@\n2'"]'@\n2'[/url], 1), ('#\n3', 1), ('$\n4', 1),
        ## ('%\n5', 1), ('^\n6', 1), ('&\n7', 1), ('*\n8', 1), ('(\n9', 1),
        ## (')\n0', 1), ('_\n-', 1), ('+\n=', 1), ('Backspace', 2)),
        If you hit reply, and read just above, you'll see what got copied to my script. The Code view seems right. You should be able to work this out with your original.

        Comment

        • bartonc
          Recognized Expert Expert
          • Sep 2006
          • 6478

          #19
          Originally posted by bartonc
          If you hit reply, and read just above, you'll see what got copied to my script. The Code view seems right. You should be able to work this out with your original.
          OK. I worked it out:
          Code:
          from Tkinter import *
          buttonData = \
          (
           ( ('~\n`', 1), ('!\n1', 1), ('@\n2', 1), ('#\n3', 1), ('$\n4', 1),
           ('%\n5', 1), ('^\n6', 1), ('&\n7', 1), ('*\n8', 1), ('(\n9', 1),
           (')\n0', 1), ('_\n-', 1), ('+\n=', 1), ('Backspace', 2)),
          
           (('Tab', 2), ('Q', 1), ('W', 1), ('E', 1), ('R', 1), ('T', 1),
           ('Y', 1), ('U', 1), ('I', 1), ('O', 1), ('P', 1), ('{\n[', 1),
           ('}\n]', 1), ('|\n\\', 1)),
          
           (('CapsLock', 2), ('A', 1), ('S', 1), ('D', 1), ('F', 1), ('G', 1),
           ('H', 1), ('J', 1), ('K', 1), ('L', 1), (':\n;', 1), ('"\n\'', 1),
           ('Enter', 2)),
          
           (('Shift', 2), ('Z', 1), ('X', 1), ('C', 1), ('V', 1), ('B', 1),
           ('N', 1), ('M', 1), ('<\n,', 1), ('>\n.', 1), ('?\n/', 1), ('Shift', 3)),
          
           (('Ctrl', 2), ('Alt', 2), ('Space', 7), ('Alt', 2), ('Ctrl', 2)),
          )
          
          
          class KeyButton(Button):
              def __init__(self, parent, label_state):
                  label = label_state[0]
                  self.btnStates = label.split()
                  self.state = label_state[1]
                  Button.__init__(self, parent, text=label, command=self.DoAction)
          
          
              def DoAction(self):
                  try:
                      print self.btnStates[self.state]
                  except IndexError:
                      print "No such state"
              def SetState(self, state):
                  self.state = state
          
          
          if __name__ == "__main__":
              root = Tk()
          
              btnList = [] # an empty list
              for rowNum, rowTuple in enumerate(buttonData):
                  for colNum, constTuple in enumerate(rowTuple):
                      keyButton=KeyButton(root, constTuple) #I put this in... NEED INNER MOST DATA!
                      keyButton.grid(row=rowNum, column=colNum)
                      btnList.append(keyButton) # a linerar list of all the buttons.
          
          
              root.mainloop()

          Comment

          • bartonc
            Recognized Expert Expert
            • Sep 2006
            • 6478

            #20
            I've gotten a better understanding, so here's a big head start. I've begun formating the screen for you.
            Code:
            from Tkinter import *
            buttonData = \
            (
             ((), (), (), ('~\n`', 1), ('!\n1', 1), ('@\n2', 1), ('#\n3', 1), ('$\n4', 1),
             ('%\n5', 1), ('^\n6', 1), ('&\n7', 1), ('*\n8', 1), ('(\n9', 1),
             (')\n0', 1), ('_\n-', 1), ('+\n=', 1), ('Backspace', 2)),
            
             ((), ('Tab', 2), (), ('Q', 1), ('W', 1), ('E', 1), ('R', 1), ('T', 1),
             ('Y', 1), ('U', 1), ('I', 1), ('O', 1), ('P', 1), ('{\n[', 1),
             ('}\n]', 1), ('|\n\\', 1)),
            
             (('CapsLock', 3), (), (), ('A', 1), ('S', 1), ('D', 1), ('F', 1), ('G', 1),
             ('H', 1), ('J', 1), ('K', 1), ('L', 1), (':\n;', 1), ('"\n\'', 1),
             ('Enter', 2)),
            
             ((), ('Shift', 2), (), ('Z', 1), ('X', 1), ('C', 1), ('V', 1), ('B', 1),
             ('N', 1), ('M', 1), ('<\n,', 1), ('>\n.', 1), ('?\n/', 1), ('Shift', 3)),
            
             ((), ('Ctrl', 2), (), ('Alt', 2), (), ('Space', 5), (), (), (), (), ('Alt', 2), (), ('Ctrl', 2)),
            )
            
            
            class KeyButton(Button):
                def __init__(self, parent, label):
                    states = label.split('\n')
                    if len(states) < 2:
                        states.append(label)
                    self.btnStates = states
                    self.state = 0
                    Button.__init__(self, parent, text=label, command=self.DoAction)
            
            
                def DoAction(self):
                    try:
                        print self.btnStates[self.state]
                    except IndexError:
                        print "No such state"
            
                def SetState(self, state):
                    self.state = state
            
            
            if __name__ == "__main__":
                root = Tk()
            
                btnList = [] # an empty list
                for rowNum, rowTuple in enumerate(buttonData):
                    for colNum, constTuple in enumerate(rowTuple):
                        if constTuple:
                            keyButton=KeyButton(root, constTuple[0]) # Send the lable to the keyButton
                            keyButton.grid(row=rowNum, column=colNum, columnspan=constTuple[1], sticky=EW)
                            btnList.append(keyButton) # a linerar list of all the buttons.
            
            
                root.mainloop()

            Comment

            • TMS
              New Member
              • Sep 2006
              • 119

              #21
              Awesome.

              One question... why build the buttons in the test program? If I was to call it from a command line, it wouldn't work, right? Just curious.

              Comment

              • bartonc
                Recognized Expert Expert
                • Sep 2006
                • 6478

                #22
                Originally posted by TMS
                Awesome.

                One question... why build the buttons in the test program? If I was to call it from a command line, it wouldn't work, right? Just curious.
                If you run this as a script (command line counts as such), __name__ will be __main__. We do this so that later you can reuse the class from another module with import.

                Comment

                • TMS
                  New Member
                  • Sep 2006
                  • 119

                  #23
                  ok, thank you. It looks really good. I did some space formatting and now I'm working on backspace and such. This is what it looks like with the formatting:


                  Code:
                  from Tkinter import *
                  buttonData = \
                  (
                   ( ('  ~  \n  `  \n ', 1), ('   !  \n 1 \n ', 1),  ('  @  \n  2  \n', 1), ('   #  \n   3  \n', 1), ('   $  \n  4  \n', 1), 
                   ('   %   \n  5   \n', 1), ('  ^  \n   6   \n', 1), ('   &   \n  7  \n', 1), ('   *   \n   8  \n', 1), ('  (   \n   9   \n', 1), 
                   ('  )   \n  0  \n', 1), ('  _  \n   -   \n', 1), ('  +  \n  =   \n', 1),  (' \n	Backspace	\n', 6), (),  ()),
                   (('  Tab  \n', 2), (),  (' Q \n', 1), (' W \n', 1), (' E \n', 1), (' R \n', 1), (' T \n', 1),
                   (' Y \n', 1), (' U \n  ', 1), (' I  \n ', 1), (' O \n ', 1), (' P \n ', 1), (' {  \n  [  ', 1), 
                   ('	}   \n	]   ', 1 ), ('	   |	   \n   \\   ', 1) ),
                   (('Caps Lock\n', 3), (), (), ('A\n', 1), ('S\n', 1), ('D\n', 1), ('F\n', 1), ('G\n', 1),
                   ('H\n', 1), ('J\n', 1), ('K\n', 1), ('L\n', 1), (':\n;', 1), ('"\n\'', 1),
                   ('Enter\n ', 2)),
                   (('Shift\n', 3), (), (), ('Z\n', 1), ('X\n', 1), ('C\n', 1), ('V\n', 1), ('B\n', 1),
                   ('N\n', 1), ('M\n', 1), ('<\n,', 1), ('>\n.', 1), ('?\n/', 1), ('Shift\n', 2)),
                   (('\nCtrl', 3), (), (), ('\nAlt', 2), (), ('\n		  Space			  ', 7), (), (),(),(),(), (), ('\nAlt', 2), (), ('\nCtrl', 2)),
                  )
                  
                  class KeyButton(Button):
                  	def __init__(self, parent, label):
                  		states = label.split('\n')
                  		if len(states) < 2:
                  			states.append(label)
                  		self.btnStates = states
                  		self.state = 0
                  		Button.__init__(self, parent, text=label, command=self.DoAction)
                  	def DoAction(self):
                  		try:
                  			print self.btnStates[self.state]
                  		except IndexError:
                  			print "No such state"
                  	def SetState(self, state):
                  		self.state = state
                  
                  if __name__ == "__main__":
                  	root = Tk()
                  	btnList = [] # an empty list
                  	for rowNum, rowTuple in enumerate(buttonData):
                  		for colNum, constTuple in enumerate(rowTuple):
                  			if constTuple:
                  				keyButton=KeyButton(root, constTuple[0]) # Send the lable to the keyButton
                  				keyButton.grid(row=rowNum, column=colNum, columnspan=constTuple[1], sticky=EW)
                  				btnList.append(keyButton) # a linerar list of all the buttons.
                  
                  	root.mainloop()
                  I'm trying to make it look like a keyboard, and on my machine it works. I will try it on a laptop later. Thank you so much for the BIG push. I'm definitely more optimistic.

                  TMS

                  Comment

                  • TMS
                    New Member
                    • Sep 2006
                    • 119

                    #24
                    OK, I don't get it. HOW did you get the space bar to print a space? I see that it works, but I don't see where you told it to do that! Please point it out, I've been going through the code and .... well, its a mystery!

                    Comment

                    • bartonc
                      Recognized Expert Expert
                      • Sep 2006
                      • 6478

                      #25
                      Originally posted by TMS
                      ok, thank you. It looks really good. I did some space formatting and now I'm working on backspace and such. This is what it looks like with the formatting:


                      Code:
                      from Tkinter import *
                      buttonData = \
                      (
                       ( ('  ~  \n  `  \n ', 1), ('   !  \n 1 \n ', 1),  ('  @  \n  2  \n', 1), ('   #  \n   3  \n', 1), ('   $  \n  4  \n', 1), 
                       ('   %   \n  5   \n', 1), ('  ^  \n   6   \n', 1), ('   &   \n  7  \n', 1), ('   *   \n   8  \n', 1), ('  (   \n   9   \n', 1), 
                       ('  )   \n  0  \n', 1), ('  _  \n   -   \n', 1), ('  +  \n  =   \n', 1),  (' \n	Backspace	\n', 6), (),  ()),
                       (('  Tab  \n', 2), (),  (' Q \n', 1), (' W \n', 1), (' E \n', 1), (' R \n', 1), (' T \n', 1),
                       (' Y \n', 1), (' U \n  ', 1), (' I  \n ', 1), (' O \n ', 1), (' P \n ', 1), (' {  \n  [  ', 1), 
                       ('	}   \n	]   ', 1 ), ('	   |	   \n   \\   ', 1) ),
                       (('Caps Lock\n', 3), (), (), ('A\n', 1), ('S\n', 1), ('D\n', 1), ('F\n', 1), ('G\n', 1),
                       ('H\n', 1), ('J\n', 1), ('K\n', 1), ('L\n', 1), (':\n;', 1), ('"\n\'', 1),
                       ('Enter\n ', 2)),
                       (('Shift\n', 3), (), (), ('Z\n', 1), ('X\n', 1), ('C\n', 1), ('V\n', 1), ('B\n', 1),
                       ('N\n', 1), ('M\n', 1), ('<\n,', 1), ('>\n.', 1), ('?\n/', 1), ('Shift\n', 2)),
                       (('\nCtrl', 3), (), (), ('\nAlt', 2), (), ('\n		  Space			  ', 7), (), (),(),(),(), (), ('\nAlt', 2), (), ('\nCtrl', 2)),
                      )
                      
                      class KeyButton(Button):
                      	def __init__(self, parent, label):
                      		states = label.split('\n')
                      		if len(states) < 2:
                      			states.append(label)
                      		self.btnStates = states
                      		self.state = 0
                      		Button.__init__(self, parent, text=label, command=self.DoAction)
                      	def DoAction(self):
                      		try:
                      			print self.btnStates[self.state]
                      		except IndexError:
                      			print "No such state"
                      	def SetState(self, state):
                      		self.state = state
                      
                      if __name__ == "__main__":
                      	root = Tk()
                      	btnList = [] # an empty list
                      	for rowNum, rowTuple in enumerate(buttonData):
                      		for colNum, constTuple in enumerate(rowTuple):
                      			if constTuple:
                      				keyButton=KeyButton(root, constTuple[0]) # Send the lable to the keyButton
                      				keyButton.grid(row=rowNum, column=colNum, columnspan=constTuple[1], sticky=EW)
                      				btnList.append(keyButton) # a linerar list of all the buttons.
                      
                      	root.mainloop()
                      I'm trying to make it look like a keyboard, and on my machine it works. I will try it on a laptop later. Thank you so much for the BIG push. I'm definitely more optimistic.

                      TMS
                      I guess that it's time to talk about inheritance: I designed this class for the general rule that a button has 2 values. The values come from the incoming label argument:
                      Code:
                      '  ~  \n  ` '.split('\n')  # for example
                      becomes
                      Code:
                      ['  ~  ', ' ` ']
                      which is saved in self.btnStates (should probably be self.btnStateTe xt)
                      DoAction() the looks at self.state and decides which of these to print.
                      I added some specialty code for buttons with no newline in the label that gave both states the same value, but at the time I was thinking that is was time for a new subclass of KeyButton or a rewrite of this one that takes more arguments ((say) label, [char1, char2]). Of course, the easiest thing to do is replace "space" with " " (I'm not sure what replacing "tab" with '\t' will do, though).
                      Code:
                      class KeyButton(Button):
                      	def __init__(self, parent, label):
                      		statesText = label.split('\n') ### see explanation above ##
                      		if len(statesText) < 2:
                      			statesText.append(label)
                      		self.btnStateText= statesText
                      		self.state = 0
                      		Button.__init__(self, parent, text=label, command=self.DoAction)
                      
                      	def DoAction(self):
                      		try:
                      			print self.btnStateText[self.state]
                      		except IndexError:
                      			print "No such state"
                      	def SetState(self, state):
                      		self.state = state

                      Comment

                      • TMS
                        New Member
                        • Sep 2006
                        • 119

                        #26
                        right... I'm looking at the code and I don't see where space is replaced with " ". I have an understanding of how you did the \n thing, so that only one of the letters or chars is printed, but I don't see where you added the functionality for "space". You have defined an action, I see that, and defined states, but I'm looking specifically where the action of the spacebar is. thanks for your patience, I'm just amazed at this whole thing!

                        Comment

                        • TMS
                          New Member
                          • Sep 2006
                          • 119

                          #27
                          nevermind... I know why.... I did a newline and its printing the space from the top line. LOL. OK, nevermind.

                          tms

                          Comment

                          • TMS
                            New Member
                            • Sep 2006
                            • 119

                            #28
                            Well, my teacher tells me the approach is all wrong. As usual, its his way or no way. Really frustrating since there is no way to develop my own style when I get things wrong if I don't do it the way he wants me to. sigh..........

                            He said the code makes the assumption that the button label determines the states and that each key maintains its own state, and that is wrong. The state applies to the whole keyboard, so 'state' should not be an attribute of the button. I suppose that means different layouts? OMG I wish I never took this class!

                            thanks for the help... sigh....

                            Comment

                            • bartonc
                              Recognized Expert Expert
                              • Sep 2006
                              • 6478

                              #29
                              Originally posted by TMS
                              Well, my teacher tells me the approach is all wrong. As usual, its his way or no way. Really frustrating since there is no way to develop my own style when I get things wrong if I don't do it the way he wants me to. sigh..........
                              I think you're doing well and if you enjoy it or get to do your own project for fun you'll develop you own style. Then everbody elses way can be wrong.
                              He said the code makes the assumption that the button label determines the states and that each key maintains its own state, and that is wrong. The state applies to the whole keyboard, so 'state' should not be an attribute of the button.
                              This is a very good point. It does complicate things a bit, though.
                              I suppose that means different layouts?
                              It just means tweaking the class a little bit. That's the beauty of this type of OOP.
                              OMG I wish I never took this class!
                              Hang in there, you'll get it.
                              thanks for the help... sigh....
                              Sorry if I created the confusion that you're going through.

                              Comment

                              • TMS
                                New Member
                                • Sep 2006
                                • 119

                                #30
                                No... you didn't create the confusion.

                                I have a new question, and I'll start a new thread. Thank you again, I really learned some stuff from this process.

                                TMS

                                Comment

                                Working...