Tkinter, and calling other classes

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • phoenix1990
    New Member
    • May 2009
    • 18

    Tkinter, and calling other classes

    Hi,
    i'm kind of new at programming, so i was just wandering if anyone can help me with a little problem that i've been having for a couple of hours now.
    i have a piece of code that's was given to me like this and can't be touched:
    ----------------------------------------------------------
    Code:
    DIGITS=4
    class EntryFrame(Frame):
        """A widget base class for entering a list of digits
    
        Constructor: EntryFrame(parent, num) - parent is the parent widget
        and num is the number of digits to be entered.
        """
    
    ----def __init__(self, parent, num):
    --------Frame.__init__(self, parent)
    --------self.entries = []
    --------self.num = num
    --------for i in range(num):
    ------------entry =  Entry(self, width=1, font=GUESSFONT)
    ------------entry.pack(side=LEFT,padx=0)
    ------------entry.bind("<Key>", self.keyevent)
    ------------self.entries.append(entry)
    --------self.entries[0].focus()
    --------self.ok = Button(self, text="Guess", command=self.guess)
    --------self.ok.pack(side=LEFT, padx=10)
    --------self.cancel = Button(self, text="Clear", command=self.clear)
    --------self.cancel.pack(side=LEFT, padx=10)
    --------self.statustext = StringVar()
    --------Label(self, textvariable=self.statustext,\
    --------------anchor=W,width=30).pack(side=LEFT)
    --------self.setStatus()
    ------------------------------------------------------------------
    i also have a master class called controller. the problem is in the controller class i want to call the entryframe class so that when i run the code it will create what the code above is going to create, but i don't know how to do that.
    i've been trying EntryFrame.__in it__(parent, DIGITS)
    but i keep getting the error global name parent is not defined.
    i don't know what to do now.
    please help.
    thanks
    phoenix1990
    Last edited by bvdet; May 12 '09, 12:55 PM. Reason: Add code tags
  • boxfish
    Recognized Expert Contributor
    • Mar 2008
    • 469

    #2
    If you don't want to specify a parent, make an EntryFrame object like this:
    Code:
    self.myEntryFrame = EntryFrame(None, DIGITS)
    I hope this is helpful.

    Comment

    • phoenix1990
      New Member
      • May 2009
      • 18

      #3
      Originally posted by boxfish
      If you don't want to specify a parent, make an EntryFrame object like this:
      Code:
      self.myEntryFrame = EntryFrame(None, DIGITS)
      I hope this is helpful.
      thank you, boxfish for replying. however that seems to have no effect on it whatsoever.
      i can specify a parent in another class if i want to, but i'm not sure how to do that. again i'm still a noob when it comes to programming.

      Comment

      • boxfish
        Recognized Expert Contributor
        • Mar 2008
        • 469

        #4
        So do you want to create an EntryFrame object as a member in your Controller class? Here is how you would do that:

        Code:
        # Put stuff for EntryFrame class up here
        
        class Controller(object):
            def __init__(self):
                self.myEntryFrame = EntryFrame(None, DIGITS)
        
        myController = Controller()
        Let me know if this is not what you're after or if you're having a problem with it.

        Comment

        • phoenix1990
          New Member
          • May 2009
          • 18

          #5
          Originally posted by boxfish
          So do you want to create an EntryFrame object as a member in your Controller class? Here is how you would do that:

          Code:
          # Put stuff for EntryFrame class up here
          
          class Controller(object):
              def __init__(self):
                  self.myEntryFrame = EntryFrame(None, DIGITS)
          
          myController = Controller()
          Let me know if this is not what you're after or if you're having a problem with it.

          yeah it turns out that the code you gave me earlier did work, i just didn't pack it into the frame.
          thanks for you help boxfish

          Comment

          • phoenix1990
            New Member
            • May 2009
            • 18

            #6
            just one more question, and it quite a long one, but don't understand how inheritence works much

            so here's the full code of the EntryFrame class
            [code]
            Code:
            DIGITS=4
            class EntryFrame(Frame):
                """A widget base class for entering a list of digits
            
                Constructor: EntryFrame(parent, num) - parent is the parent widget
                and num is the number of digits to be entered.
                """
            
            ----def __init__(self, parent, num):
            --------Frame.__init__(self, parent)
            --------self.entries = []
            --------self.num = num
            --------for i in range(num):
            ------------entry =  Entry(self, width=1, font=GUESSFONT)
            ------------entry.pack(side=LEFT,padx=0)
            ------------entry.bind("<Key>", self.keyevent)
            ------------self.entries.append(entry)
            --------self.entries[0].focus()
            --------self.ok = Button(self, text="Guess", command=self.guess)
            --------self.ok.pack(side=LEFT, padx=10)
            --------self.cancel = Button(self, text="Clear", command=self.clear)
            --------self.cancel.pack(side=LEFT, padx=10)
            --------self.statustext = StringVar()
            --------Label(self, textvariable=self.statustext,\
            --------------anchor=W,width=30).pack(side=LEFT)
            --------self.setStatus()
            
                def keyevent(self, e):
                    """The key event callback."""
            
                    index = self.entries.index(e.widget)
                    v = e.char
                    sym = e.keysym
                    if sym == 'Right':              # rightarrow
                        index = (index+1)%self.num
                        self.entries[index].icursor(END)
                        self.entries[index].focus()
                        self.entries[index].select_range(0,END)
                    elif sym == 'Left':             # leftarrow
                        index = (index-1)%self.num
                        self.entries[index].icursor(END)
                        self.entries[index].focus()
                        self.entries[index].select_range(0,END)
            
                    elif sym == 'BackSpace':  
                        if index > 0 and self.entries[index].get() == '':
                            index -= 1
                            self.entries[index].focus()
                            self.entries[index].select_range(0,END)
                        self.after_idle(self.handleEntries, index)
                    elif sym == 'Return':           # enter
                        self.guess()
                    elif sym == "Delete":
                        self.clear()
                    elif v.isdigit():
                        self.entries[index].delete(0,END)
                        if index < self.num-1:
                            index +=1
                        self.after_idle(self.handleEntries, index)
                        self.entries[index].focus()
                        self.entries[index].select_range(0,END)
                    elif v and (v.isalpha() or v in CHARS):
                        self.entries[index].delete(0,END)
                        self.handleEntries(index)
                        return "break"
            
                def clear(self):
                    """Clear all the entries."""
            
                    for i in range(self.num):
                        self.entries[i].delete(0,END)
                        self.handleEntries(i)
                    self.entries[0].focus()
                    self.setStatus()
            
                def handleEntries(self, index):
                    """The after_idle callback - highlight the text in the current
                    entry and process the entries
                    """
            
                    self.entries[index].select_range(0,END)
                    self.processEntries()
            
                def guess(self):
                    """Called when a guess is entered - to be overridden
                    in the subclass."""
            
                    pass
            
                def processEntries(self):
                    """Called whenever a digit is added or deleted - to be overridden
                    in the subclass."""
            
                    pass
            
                def setStatus(self):
                    """Set the text in the status label - - to be overridden
                    in the subclass."""
            
                    self.statustext.set("Status:")
            what i want to know is how do i go about creating another class which inherits from EntryFrame. and overrides the setstatus definition. if someone can show me how to just do the setstatus part i should be able to get the rest on my own. all it needs to do is say that if there are duplicate numbers entered, it would say 'Repeared Digits', but if there are no duplicates then it would say 'Ready' next to the word 'Status:'

            sorry for asking soo much questions, but i really appreciate you help.

            Comment

            • boxfish
              Recognized Expert Contributor
              • Mar 2008
              • 469

              #7
              Sorry for the long response time. You can just define a new setStatus function in your new class and it will override the old one. If you want to call the old one from the new one, do this:
              Code:
              EntryFrame.setStatus(self)

              Comment

              • phoenix1990
                New Member
                • May 2009
                • 18

                #8
                Originally posted by boxfish
                Sorry for the long response time. You can just define a new setStatus function in your new class and it will override the old one. If you want to call the old one from the new one, do this:
                Code:
                EntryFrame.setStatus(self)
                is this what had. i think it's a little different to what you are saying i should do
                Code:
                class View(EntryFrame):
                    def __init__(self, parent, num):
                        EntryFrame.__init__(self, parent, num)
                        self.pack(anchor=W)
                    def setStatus(self):
                        n=0
                        for i in self.entries:
                            if i in self.entries[n+1:]: #not too sure on this part
                                self.statustext.set('Status: Repeated Digits')
                            elif len(self.entries)==4:
                                self.statustext.set('Status: Ready')
                            else:
                                self.statustext.set('Status:')
                            n+=1
                that works a bit, but every time i type in a entry in the gui it doesn't show up with the proper status text, it just stays on the one text. So how do i go about making it so that the controller class will constantly update the gui according to the entries that were entered?

                Comment

                • boxfish
                  Recognized Expert Contributor
                  • Mar 2008
                  • 469

                  #9
                  I think you also need to override the processEntries function so it calls the setStatus function. As for the setStatus function, I think you are treating the list of entries like a list of strings. I suggest getting a list of strings from the entries then working with that. But then again, the entries can only contain digits, right? How about making a list of ints:
                  Code:
                  entryDigits = []
                  for i in self.entries:
                      entryDigits.append(int(i.get()))
                  As for the repeated digits part, you have to finish checking for repeated digits before you decide what status to write. I know xrange(len(entr yDigits)) is ugly, but this loop should check for repeated digits:
                  Code:
                  repeatedDigits = False
                  for i in xrange(len(entryDigits)): # Loop through indices of entryDigits.
                      for j in entryDigits[i+1:]: # Loop through items in remaining part of entryDigits.
                          if j == entryDigits[i]: # Uh oh, repeated digit!
                              repeatedDigits = True # Set the flag.
                              break # Stop looking for repeated digits.
                      if repeatedDigits:
                          break # Make sure we stop looking for repeated digits.
                  I hope this is helpful. Let me know if it's not working.
                  Last edited by boxfish; May 16 '09, 04:32 PM. Reason: Needs more breaks.

                  Comment

                  • phoenix1990
                    New Member
                    • May 2009
                    • 18

                    #10
                    so i overrode the process entries to call the setStatus function, and everything seems to be working. however
                    Code:
                    entryDigits = []
                    for i in self.entries:
                        entryDigits.append(int(i.get()))
                    won't work since every entry in self.entries is a string and each entry initally starts off as an empty string. so it can't turn an empty string into an integer. so i decided to remove the init and that seemed to work, but now it always says "Status: Repeated Digits" since the repeated digits code will initially see 4 lots of empty strings in the entryDigits list. the only time it changes is when all four entries have been filled in the GUI, and none of them are the same.

                    Comment

                    • phoenix1990
                      New Member
                      • May 2009
                      • 18

                      #11
                      nevermind i got it to work in the end, by adding this in
                      Code:
                              
                      entryDigits = []
                      for i in self.entries:
                          entryDigits.append(i.get())
                          for i in entryDigits:
                              if i=='':
                                  entryDigits.remove(i)

                      Comment

                      • boxfish
                        Recognized Expert Contributor
                        • Mar 2008
                        • 469

                        #12
                        While that code will work, it is doing a lot more work than it needs to. The fact that the for loops are nested means that the inner one is being executed over and over again. Try this:
                        Code:
                        entryDigits = []
                        for i in self.entries:
                            if i.get():
                                entryDigits.append(int(i.get()))
                        I hope this is helpful.

                        Comment

                        • phoenix1990
                          New Member
                          • May 2009
                          • 18

                          #13
                          thanks for the help boxfish.
                          if i run into anymore problems i'll let you know

                          Comment

                          • phoenix1990
                            New Member
                            • May 2009
                            • 18

                            #14
                            ok so i've run into a problem with the code you gave me. when i click clear. it runs the clear definition that was defined in the entryframe class. however it will only delete the first entry in the GUI's frame and not the other three..

                            Comment

                            • phoenix1990
                              New Member
                              • May 2009
                              • 18

                              #15
                              Originally posted by phoenix1990
                              ok so i've run into a problem with the code you gave me. when i click clear. it runs the clear definition that was defined in the entryframe class. however it will only delete the first entry in the GUI's frame and not the other three..
                              nevermind, it fixed itself somehow.

                              Comment

                              Working...