TKinter, buttonwidget response problem(1) and all btns the same size(2)!

skanemupp at yahoo.se skanemupp at yahoo.se
Sat Apr 5 01:02:45 EDT 2008


On 5 Apr, 05:57, skanem... at yahoo.se wrote:
> On 5 Apr, 05:26, 7stud <bbxx789_0... at yahoo.com> wrote:
>
>
>
> > On Apr 4, 7:06 pm, skanem... at yahoo.se wrote:
>
> > > 1st question:
>
> > > when i run this program 1 will be printed into the interpreter when i
> > > run it BUT without me clicking the actual button.
> > > when i then click the button "1", nothing happens.
>
> > > obv i dont want any output when i dont push the button but i want it
> > > when i do.
>
> > > what am i doing wrong here?
>
> > > 2nd question:
>
> > > i want all the buttons to have the same size. i thought i should use
> > > row/columnspan but i dont get that to work.
> > > how should i do?
>
> > > [code]
> > > #! /usr/bin/env python
> > > from Tkinter import *
> > > import tkMessageBox
>
> > > class GUIFramework(Frame):
> > >     """This is the GUI"""
>
> > >     def __init__(self,master=None):
> > >         """Initialize yourself"""
>
> > >         """Initialise the base class"""
> > >         Frame.__init__(self,master)
>
> > >         """Set the Window Title"""
> > >         self.master.title("Calculator")
>
> > >         """Display the main window"
> > >         with a little bit of padding"""
> > >         self.grid(padx=10,pady=10)
> > >         self.CreateWidgets()
>
> > >     def CreateWidgets(self):
>
> > >         self.enText = Entry(self)
> > >         self.enText.grid(row=0, column=0, columnspan=8, padx=5,
> > > pady=5)
>
> > >         self.enText = Entry(self)
> > >         self.enText.grid(row=1, column=0, columnspan=8, padx=5,
> > > pady=5)
>
> > >         self.btnDisplay = Button(self, text="1",
> > > command=self.Display(1))
> > >         self.btnDisplay.grid(row=3, column=0, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="2", default=ACTIVE)
> > >         self.btnDisplay.grid(row=3, column=1, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="3", default=ACTIVE)
> > >         self.btnDisplay.grid(row=3, column=2, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="+", default=ACTIVE)
> > >         self.btnDisplay.grid(row=3, column=3, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="4", default=ACTIVE)
> > >         self.btnDisplay.grid(row=4, column=0, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="5", default=ACTIVE)
> > >         self.btnDisplay.grid(row=4, column=1, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="6", default=ACTIVE)
> > >         self.btnDisplay.grid(row=4, column=2, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="-", default=ACTIVE)
> > >         self.btnDisplay.grid(row=4, column=3, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="7", default=ACTIVE)
> > >         self.btnDisplay.grid(row=5, column=0, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="8", default=ACTIVE)
> > >         self.btnDisplay.grid(row=5, column=1, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="9", default=ACTIVE)
> > >         self.btnDisplay.grid(row=5, column=2, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="*", default=ACTIVE)
> > >         self.btnDisplay.grid(row=5, column=3, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="0", default=ACTIVE)
> > >         self.btnDisplay.grid(row=6, column=0, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="C", default=ACTIVE)
> > >         self.btnDisplay.grid(row=6, column=1, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="r", default=ACTIVE)
> > >         self.btnDisplay.grid(row=6, column=2, padx=5, pady=5)
>
> > >         self.btnDisplay = Button(self, text="/", default=ACTIVE)
> > >         self.btnDisplay.grid(row=6, column=3, padx=5, pady=5)
>
> > >     def Display(self, xbtn):
> > >         if xbtn==1:
> > >             print 1
>
> > > if __name__ == "__main__":
> > >     guiFrame = GUIFramework()
> > >     guiFrame.mainloop()
>
> > > [/code]
>
> > If you have this function:
>
> > def f():
> >    print 1
> >    return 10
>
> > and you write:
>
> > result = f()
>
> > The '()' is the function execution operator; it tells python to
> > execute the function.  In this case, the function executes, and then
> > the return value of the function is assigned to the variable result.
> > If a function does not have a return statement, then the function
> > returns None by default.
>
> > The same thing is happening in this portion of your code:
>
> > command = self.Display(1)
>
> > That code tells python to execute the Display function and assign the
> > function's return value to the variable command.  As a result Display
> > executes and 1 is displayed.  Then since Dispay does not have a return
> > statement, None is returned, and None is assigned to command.
> > Obviously, that is not what you want to do.
>
> > What you want to do is assign a "function reference" to command so
> > that python can execute the function sometime later when you click on
> > the button.  A function reference is just the function name without
> > the '()' after it.  So you would write:
>
> > command = self.Display
>
> > But writing it like that doesn't allow *you* to pass any arguments to
> > Display().  In addition, *tkinter* does not pass any arguments to
> > Display when tkinter calls Display in response to a button click.  As
> > a result, there is no way to pass an argument to Display.
>
> > However, there is another way to cause a function to execute when an
> > event, like a button click, occurs on a widget: you use the widget's
> > bind() function:
>
> > my_button.bind('<Button-1>', someFunc)
>
> > The first argument tells tkinter what event to respond to.
> > '<Button-1>' is a left click.  Check the docs for the different
> > strings that represent the different events that you can respond to.
> > The second argument is a function reference, which once again does not
> > allow you to pass any arguments to the function.  However, when you
> > use bind() to attach a function to a widget, tkinter calls the
> > function and passes it one argument: the "event object".  The event
> > object contains various pieces of information, and one piece of
> > information it contains is the widget upon which the event occurred,
> > e.g. the button that was clicked.  To get the button, you write:
>
> > Display(self, event_obj):
> >     button = event_obj.widget
>
> > Once you have the button, you can get the text on the button:
>
> > Display(self, event_obj):
> >     button = event_obj.widget
> >     text = button.cget("text")
>
> >     if text=="1":
> >         print 1
>
> > Another thing you should be aware of: self is like a class wide
> > bulletin board. If you are writing code inside a class method, and
> > there is data that you want code inside another class method to be
> > able to see, then post the data on the class wide bulletin board, i.e.
> > attach it to self.  But in your code, you are doing this:
>
> > self.btnDisplay = Button(self, text="7", default=ACTIVE)
> > self.btnDisplay.grid(row=5, column=0, padx=5, pady=5)
>
> > self.btnDisplay = Button(self, text="8", default=ACTIVE)
> > self.btnDisplay.grid(row=5, column=1, padx=5, pady=5)
>
> > As a result, your code continually overwrites self.btnDisplay.  That
> > means you aren't preserving the data assigned to self.btnDisplay.
> > Therefore, the data does not need to be posted on the class wide
> > bulletin board for other class methods to see.  So just write:
>
> > btnDisplay = Button(self, text="7", default=ACTIVE)
> > btnDisplay.grid(row=5, column=0, padx=5, pady=5)
>
> > btnDisplay = Button(self, text="8", default=ACTIVE)
> > btnDisplay.grid(row=5, column=1, padx=5, pady=5)
>
> > As for the button sizing problem, your buttons are all the same size
> > and line up perfectly on mac os x 10.4.7.
>
> wow thank you so much, awesome answer i will get right to fixing this
> now.
>
> in regards to the buttonsizes i use windows VISTA and they have
> different sizes.



one thing i dont rally get, i ahve to add my_button.bind() somewhere?
i changed the stuff u said though and i get this error(the program
executes though and i can press the buttons):

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python25\lib\lib-tk\Tkinter.py", line 1403, in __call__
    return self.func(*args)
TypeError: Display() takes exactly 2 arguments (1 given)


current version:
#! /usr/bin/env python
from Tkinter import *
import tkMessageBox

class GUIFramework(Frame):
    """This is the GUI"""

    def __init__(self,master=None):
        """Initialize yourself"""

        """Initialise the base class"""
        Frame.__init__(self,master)

        """Set the Window Title"""
        self.master.title("Calculator")

        """Display the main window"
        with a little bit of padding"""
        self.grid(padx=10,pady=10)
        self.CreateWidgets()

    def CreateWidgets(self):

        enText = Entry(self)
        enText.grid(row=0, column=0, columnspan=8, padx=5, pady=5)

        enText = Entry(self)
        enText.grid(row=1, column=0, columnspan=8, padx=5, pady=5)

        btnDisplay = Button(self, text="1", command=self.Display)
        btnDisplay.grid(row=3, column=0, padx=5, pady=5)

        btnDisplay = Button(self, text="2", default=ACTIVE)
        btnDisplay.grid(row=3, column=1, padx=5, pady=5)

        btnDisplay = Button(self, text="3", default=ACTIVE)
        btnDisplay.grid(row=3, column=2, padx=5, pady=5)

        btnDisplay = Button(self, text="+", default=ACTIVE)
        btnDisplay.grid(row=3, column=3, padx=5, pady=5)

        btnDisplay = Button(self, text="4", default=ACTIVE)
        btnDisplay.grid(row=4, column=0, padx=5, pady=5)

        self.btnDisplay = Button(self, text="5", default=ACTIVE)
        self.btnDisplay.grid(row=4, column=1, padx=5, pady=5)

        btnDisplay = Button(self, text="6", default=ACTIVE)
        btnDisplay.grid(row=4, column=2, padx=5, pady=5)

        btnDisplay = Button(self, text="-", default=ACTIVE)
        btnDisplay.grid(row=4, column=3, padx=5, pady=5)

        btnDisplay = Button(self, text="7", default=ACTIVE)
        btnDisplay.grid(row=5, column=0, padx=5, pady=5)

        btnDisplay = Button(self, text="8", default=ACTIVE)
        btnDisplay.grid(row=5, column=1, padx=5, pady=5)

        btnDisplay = Button(self, text="9", default=ACTIVE)
        btnDisplay.grid(row=5, column=2, padx=5, pady=5)

        btnDisplay = Button(self, text="*", default=ACTIVE)
        btnDisplay.grid(row=5, column=3, padx=5, pady=5)

        btnDisplay = Button(self, text="0", default=ACTIVE)
        btnDisplay.grid(row=6, column=0, padx=5, pady=5)

        btnDisplay = Button(self, text="C", default=ACTIVE)
        btnDisplay.grid(row=6, column=1, padx=5, pady=5)

        btnDisplay = Button(self, text="r", default=ACTIVE)
        btnDisplay.grid(row=6, column=2, padx=5, pady=5)

        btnDisplay = Button(self, text="/", default=ACTIVE)
        btnDisplay.grid(row=6, column=3, padx=5, pady=5)
        #self.btnDisplay(expand=0/1)

##    def Display(self, xbtn):
##        if xbtn==1:
##            print 1

    def Display(self, event_obj):
        button = event_obj.widget
        text = button.cget("text")

        if text=="1":
            print 1

if __name__ == "__main__":
    guiFrame = GUIFramework()
    guiFrame.mainloop()




More information about the Python-list mailing list