Tkinter Spinbox

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • 5N1P3R
    New Member
    • May 2007
    • 7

    #1

    Tkinter Spinbox

    Hi

    I need a spinbox which when created can read a variable (which is an integer) from another location and use that variable for the starting value. i also need to only allow integers be input into the text field by keyboard (and only has high as 999). lastly, whenever the spinbox value is changed (either by keyboard input or by clicking on the arrows) i need to be able to verify that it is an integer and then save its value into another location.

    i have tried to do these things but without success. currently i have this (it has been cut out of my main program:

    Code:
     resistanceEntry = Spinbox(resistorFrame, from_=1, to=999, width=10, wrap=True, validate=ALL, validatecommand=validate)
    
    def validate():
        print "VALIDATE"
    i noticed that even with validate set to ALL it only runs the command validate once and that is when the spinbox is first created.

    any help would be greatly appreciated, but please try and keep it simple i am still very new to this

    thanks
  • bartonc
    Recognized Expert Expert
    • Sep 2006
    • 6478

    #2
    Originally posted by 5N1P3R
    Hi

    I need a spinbox which when created can read a variable (which is an integer) from another location and use that variable for the starting value. i also need to only allow integers be input into the text field by keyboard (and only has high as 999). lastly, whenever the spinbox value is changed (either by keyboard input or by clicking on the arrows) i need to be able to verify that it is an integer and then save its value into another location.

    i have tried to do these things but without success. currently i have this (it has been cut out of my main program:

    Code:
     resistanceEntry = Spinbox(resistorFrame, from_=1, to=999, width=10, wrap=True, validate=ALL, validatecommand=validate)
    
    def validate():
        print "VALIDATE"
    i noticed that even with validate set to ALL it only runs the command validate once and that is when the spinbox is first created.

    any help would be greatly appreciated, but please try and keep it simple i am still very new to this

    thanks
    Electronics huh?
    I'm guessing that you need to associate a Variable class object that gets changes. I'll have a look tonight. Got to go at the moment.

    Comment

    • bartonc
      Recognized Expert Expert
      • Sep 2006
      • 6478

      #3
      Originally posted by 5N1P3R
      Hi

      I need a spinbox which when created can read a variable (which is an integer) from another location and use that variable for the starting value. i also need to only allow integers be input into the text field by keyboard (and only has high as 999). lastly, whenever the spinbox value is changed (either by keyboard input or by clicking on the arrows) i need to be able to verify that it is an integer and then save its value into another location.

      i have tried to do these things but without success. currently i have this (it has been cut out of my main program:

      Code:
       resistanceEntry = Spinbox(resistorFrame, from_=1, to=999, width=10, wrap=True, validate=ALL, validatecommand=validate)
      
      def validate():
          print "VALIDATE"
      i noticed that even with validate set to ALL it only runs the command validate once and that is when the spinbox is first created.

      any help would be greatly appreciated, but please try and keep it simple i am still very new to this

      thanks
      Nice job on the CODE tags. Thanks. I like you naming style, too.

      Validators must return True or False:
      Code:
       resistanceEntry = Spinbox(resistorFrame, from_=1, to=999, width=10, wrap=True, validate=ALL, validatecommand=validate)
      
      def validate():
          print "VALIDATE" 
          return True
      Perhaps returning None is causing the problem.

      Comment

      • 5N1P3R
        New Member
        • May 2007
        • 7

        #4
        thank you so much :) when i return true then it validates every time, now all i need is get the spinbox value to start at a specific value, any ideas?

        Comment

        • 5N1P3R
          New Member
          • May 2007
          • 7

          #5
          EDIT: also how would i write the validate function i had the idea of this (below) but it seems very inefficient there must be a better way

          Code:
           
          def validate(input)
             for i in range (1000):
                if i == input:
                   return True
             (...etc...)

          Comment

          • bvdet
            Recognized Expert Specialist
            • Oct 2006
            • 2851

            #6
            Originally posted by 5N1P3R
            EDIT: also how would i write the validate function i had the idea of this (below) but it seems very inefficient there must be a better way

            Code:
             
            def validate(input)
               for i in range (1000):
                  if i == input:
                     return True
               (...etc...)
            Something like this:
            Code:
            >>> def validate(v):
            ... 	if isinstance(v, int) and v > 0 and v < 1000:
            ... 		return True
            ... 	else:
            ... 		return False
            ... 	
            >>> validate(6)
            True
            >>> validate(0)
            False
            >>> validate(999)
            True
            >>> validate(1000)
            False
            >>> if validate(v):
            ... 	print 'Do some stuff'
            ... 	
            Do some stuff
            >>>

            Comment

            • bartonc
              Recognized Expert Expert
              • Sep 2006
              • 6478

              #7
              Originally posted by 5N1P3R
              thank you so much :) when i return true then it validates every time, now all i need is get the spinbox value to start at a specific value, any ideas?
              In the Frame's __init__(), keep a reference:
              Code:
              self.resistanceEntry = Spinbox(resistorFrame, from_=1, to=999, width=10, wrap=True, validate=ALL, validatecommand=validate)
              Then, any time you want to, the a Frame method can
              Code:
              resistanceEntry.set(value)
              or you can might be able to
              Code:
              STARTVALUE = 100   # or whatever
              resistanceEntry = Spinbox(resistorFrame, from_=1, to=999,
                                        value=STARTVALUE, width=10, wrap=True,
                                        validate=ALL, validatecommand=validate)
              Of, course, you'll have to experiment because I have not tested this.

              Do you know where to find/have the on-line Tkinter reference???

              Comment

              • bartonc
                Recognized Expert Expert
                • Sep 2006
                • 6478

                #8
                Originally posted by bartonc
                In the Frame's __init__(), keep a reference:
                Code:
                self.resistanceEntry = Spinbox(resistorFrame, from_=1, to=999, width=10, wrap=True, validate=ALL, validatecommand=validate)
                Then, any time you want to, the a Frame method can
                Code:
                resistanceEntry.set(value)
                or you can might be able to
                Code:
                STARTVALUE = 100   # or whatever
                resistanceEntry = Spinbox(resistorFrame, from_=1, to=999,
                                          value=STARTVALUE, width=10, wrap=True,
                                          validate=ALL, validatecommand=validate)
                Of, course, you'll have to experiment because I have not tested this.

                Do you know where to find/have the on-line Tkinter reference???
                Actually, I think that the proper way to do this is with and IntVar. There is a discussion here.

                The Tkinter (old and incomplete) reference is here.

                We'll make a Pythoneer out of you, yet!

                Comment

                • 5N1P3R
                  New Member
                  • May 2007
                  • 7

                  #9
                  Originally posted by bvdet
                  Something like this:
                  Code:
                  >>> def validate(v):
                  ... 	if isinstance(v, int) and v > 0 and v < 1000:
                  ... 		return True
                  ... 	else:
                  ... 		return False
                  ... 	
                  >>> validate(6)
                  True
                  >>> validate(0)
                  False
                  >>> validate(999)
                  True
                  >>> validate(1000)
                  False
                  >>> if validate(v):
                  ... 	print 'Do some stuff'
                  ... 	
                  Do some stuff
                  >>>
                  this is perfect except how would you write isinstance? (its not a built in is it?)

                  i have taken in all of the other things people have written and just have one more question: i noticed that if i use the validatecommand function as used below then the validation is always one step behind. ie if the spinbox contains 5 and i change it to 6 it will verify the old value of 5 and then change the spinbox value of 6, thus it is always one step behind. is there any way to fix this or is there a way around it?

                  Code:
                  resistorProperties.resistanceEntry = Spinbox(resistorProperties.resistorFrame, from_=1, to=999, width=10, wrap=True, validate="all", validatecommand=validate)  #use get() to find entry
                      resistorProperties.resistanceEntry.grid(column=1, row=1, sticky=N+E)
                  
                  def validate():
                      print "VALIDATE"
                      
                      if resistorProperties.resistanceEntry == None:
                          return True
                      else:
                          toValidate = resistorProperties.resistanceEntry.get()
                  
                      print toValidate   
                      return True

                  Comment

                  • 5N1P3R
                    New Member
                    • May 2007
                    • 7

                    #10
                    Originally posted by 5N1P3R
                    this is perfect except how would you write isinstance? (its not a built in is it?)
                    worked that part out, only the second part applies :)

                    Comment

                    • bartonc
                      Recognized Expert Expert
                      • Sep 2006
                      • 6478

                      #11
                      Originally posted by 5N1P3R
                      worked that part out, only the second part applies :)
                      I fixed the event-sequence problem using an IntVar and trace().
                      I will ask you to consider designing you resistor model as a subclass of Frame, as follows:
                      Code:
                      class ResistorModel(Frame):
                          """A subclass of Tkinter.Frame for modeling a resistor using IntVar."""
                          def __init__(self, root, powerRating, *args, **kwargs):
                              Frame.__init__(self, root, *args, **kwargs)
                              self.powerRating = powerRating
                              self.Ohms = IntVar()
                              self.Ohms.trace('w', self.validateOhms)
                      
                      ##        label = Label()
                      
                              self.resistanceEntry = Spinbox(self, from_=1, to=999, width=10, wrap=True,
                                                             validate="all", textvariable=self.Ohms)  #use get() to find entry
                      ##        self.resistanceEntry.config(validatecommand=self.validateOhms)
                              self.resistanceEntry.grid(column=1, row=1, sticky=N+E)
                      
                          def validateOhms(self, *args):
                              print "VALIDATE OHMS"
                              toValidate = self.Ohms.get()
                      
                              print toValidate, type(toValidate)
                              return True
                      
                      
                      if __name__ == "__main__":
                          root = Tk()
                      
                          frame = ResistorModel(root, 10)
                          frame.pack()

                      Comment

                      • 5N1P3R
                        New Member
                        • May 2007
                        • 7

                        #12
                        Originally posted by bartonc
                        I fixed the event-sequence problem using an IntVar and trace().
                        I will ask you to consider designing you resistor model as a subclass of Frame, as follows:
                        Code:
                        class ResistorModel(Frame):
                            """A subclass of Tkinter.Frame for modeling a resistor using IntVar."""
                            def __init__(self, root, powerRating, *args, **kwargs):
                                Frame.__init__(self, root, *args, **kwargs)
                                self.powerRating = powerRating
                                self.Ohms = IntVar()
                                self.Ohms.trace('w', self.validateOhms)
                        
                        ##        label = Label()
                        
                                self.resistanceEntry = Spinbox(self, from_=1, to=999, width=10, wrap=True,
                                                               validate="all", textvariable=self.Ohms)  #use get() to find entry
                        ##        self.resistanceEntry.config(validatecommand=self.validateOhms)
                                self.resistanceEntry.grid(column=1, row=1, sticky=N+E)
                        
                            def validateOhms(self, *args):
                                print "VALIDATE OHMS"
                                toValidate = self.Ohms.get()
                        
                                print toValidate, type(toValidate)
                                return True
                        
                        
                        if __name__ == "__main__":
                            root = Tk()
                        
                            frame = ResistorModel(root, 10)
                            frame.pack()

                        wow it works :) thank you so much your code is fantastic and with minimal modification this can easily be placed directly into my program.

                        i apologise for the late reply but i have been swamped over the last few weeks and have not had any time to work on my program

                        :)

                        Comment

                        • bartonc
                          Recognized Expert Expert
                          • Sep 2006
                          • 6478

                          #13
                          Originally posted by 5N1P3R
                          wow it works :) thank you so much your code is fantastic and with minimal modification this can easily be placed directly into my program.

                          i apologise for the late reply but i have been swamped over the last few weeks and have not had any time to work on my program

                          :)
                          I was just wondering about you today. Thank you for the update.
                          Keep posting, (like some working code, maybe)
                          Barton

                          Comment

                          Working...