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


S

skanemupp

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

Advertisements

7

7stud

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



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.
 
S

skanemupp

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[/QUOTE]
[QUOTE]
class GUIFramework(Frame):
"""This is the GUI"""[/QUOTE]
[QUOTE]
def __init__(self,master=None):
"""Initialize yourself"""[/QUOTE]
[QUOTE]
"""Initialise the base class"""
Frame.__init__(self,master)[/QUOTE]
[QUOTE]
"""Set the Window Title"""
self.master.title("Calculator")[/QUOTE]
[QUOTE]
"""Display the main window"
with a little bit of padding"""
self.grid(padx=10,pady=10)
self.CreateWidgets()[/QUOTE]
[QUOTE]
def CreateWidgets(self):[/QUOTE]
[QUOTE]
self.enText = Entry(self)
self.enText.grid(row=0, column=0, columnspan=8, padx=5,
pady=5)[/QUOTE]
[QUOTE]
self.enText = Entry(self)
self.enText.grid(row=1, column=0, columnspan=8, padx=5,
pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="1",
command=self.Display(1))
self.btnDisplay.grid(row=3, column=0, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="2", default=ACTIVE)
self.btnDisplay.grid(row=3, column=1, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="3", default=ACTIVE)
self.btnDisplay.grid(row=3, column=2, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="+", default=ACTIVE)
self.btnDisplay.grid(row=3, column=3, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="4", default=ACTIVE)
self.btnDisplay.grid(row=4, column=0, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="5", default=ACTIVE)
self.btnDisplay.grid(row=4, column=1, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="6", default=ACTIVE)
self.btnDisplay.grid(row=4, column=2, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="-", default=ACTIVE)
self.btnDisplay.grid(row=4, column=3, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="7", default=ACTIVE)
self.btnDisplay.grid(row=5, column=0, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="8", default=ACTIVE)
self.btnDisplay.grid(row=5, column=1, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="9", default=ACTIVE)
self.btnDisplay.grid(row=5, column=2, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="*", default=ACTIVE)
self.btnDisplay.grid(row=5, column=3, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="0", default=ACTIVE)
self.btnDisplay.grid(row=6, column=0, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="C", default=ACTIVE)
self.btnDisplay.grid(row=6, column=1, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="r", default=ACTIVE)
self.btnDisplay.grid(row=6, column=2, padx=5, pady=5)[/QUOTE]
[QUOTE]
self.btnDisplay = Button(self, text="/", default=ACTIVE)
self.btnDisplay.grid(row=6, column=3, padx=5, pady=5)[/QUOTE]
[QUOTE]
def Display(self, xbtn):
if xbtn==1:
print 1[/QUOTE]
[QUOTE]
if __name__ == "__main__":
guiFrame = GUIFramework()
guiFrame.mainloop()[/QUOTE]
[QUOTE]

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.
 
S

skanemupp

On Apr 4, 7:06 pm, (e-mail address removed) 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()
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()
 
S

skanemupp

On Apr 4, 7:06 pm, (e-mail address removed) 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()
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,...

läs mer »


and the self. i erased, should i do it in the def __init__ as well or
only as i did in createwidgets-function?
 
G

Gabriel Genellina

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

Either use command, or bind. command requires a function with no
parameters (or a bound method with self alone). bind uses a function with
a single parameter, the event (or a bound method with self and event
parameters).

See the Tkinter book:
http://www.effbot.org/tkinterbook/tkinter-events-and-bindings.htm
http://www.effbot.org/tkinterbook/button.htm
 
Ad

Advertisements

S

skanemupp

am i not doing that then? did u look at the code? where do i add the
bind if this:
btnDisplay = Button(self, text="1", command=self.Display)
btnDisplay.grid(row=3, column=0, padx=5, pady=5)

is not enough?



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

if text=="1":
print 1



i get this exception so i need to pass another argument? im passing 2
no?

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

Marc 'BlackJack' Rintsch

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)

That's a bad idea because now the `Button` doesn't act like a typical
button anymore. This "fires" *always* and as soon as you press the mouse
button on it. Compare this with the usual and from end users point of
view expected behavior that pressing down the mouse button "presses" the
button widget visually but doesn't cause any action until you release the
button while still over it. This for instance makes it possible to change
your mind and move the mouse cursor out of the buttons area with a pressed
mouse button and prevent the action of that button.

The preferred way to bind actions to `Button`\s is the `command` argument.

The function is called with no arguments when the button is pressed, so it
has to know all data it needs to fulfill its task. Usually this is done
with anonymous functions and bound default values for short pieces of
"variable" data::

def __init__(self):
# ...
button = Button(self,
text='1',
command=lambda n=1: self.display(n))
# ...

def display(self, number):
print number

Ciao,
Marc 'BlackJack' Rintsch
 
7

7stud

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)


You still have this in your code:

btnDisplay = Button(self, text="1", command=self.Display)

I suggest you reread my earlier post again. Or, follow the advice
given by Marc 'BlackJack' Rintsch (preferable). But whatever you do,
don't use both command and bind().
 
G

Gabriel Genellina

am i not doing that then? did u look at the code? where do i add the
bind if this:
btnDisplay = Button(self, text="1", command=self.Display)
btnDisplay.grid(row=3, column=0, padx=5, pady=5)

is not enough?

Yes, I looked at the code, andn I don't see the word "bind" anywhere, do
you?
def Display(self, event_obj):
button = event_obj.widget
text = button.cget("text")

if text=="1":
print 1

This Display method is OK for *bind* but you're using *command*. Read the
previous response and in particular the Tkinter book - from the same guy
who wrote the library.
 
S

Steve Holden

and the self. i erased, should i do it in the def __init__ as well or
only as i did in createwidgets-function?

Your posts would be easier to consider if you trimmed out the stuff
that's no longer relevant. I for one pretty much just skipped over them
because of their tedious length.

Just thought I'd mention it.

regards
Steve
 
Ad

Advertisements

F

Francesco Bochicchio

Il Fri, 04 Apr 2008 20:26:13 -0700, 7stud ha scritto:
....


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.

It should be added here that in Python you have several ways get around
this Tkinter limitation and pass an user argument to the callback. Once
upon a time , back in Python 1.x, I used to do something like this:

class CallIt:
def __init__(self, f, *args):
self.f = f
self.args = args
def __call__(self):
return apply(self.f, self.args)

and then, to do what the OP wanted to do:
command = CallIt(self.Display, 1)

but nowadays, you can achieve the same effect with:
command = functtools.partial(self.Display,1)

Ciao
 
F

Fredrik Lundh

Francesco said:
It should be added here that in Python you have several ways get around
this Tkinter limitation and pass an user argument to the callback. Once
upon a time , back in Python 1.x, I used to do something like this:

class CallIt:
def __init__(self, f, *args):
self.f = f
self.args = args
def __call__(self):
return apply(self.f, self.args)

and then, to do what the OP wanted to do:
command = CallIt(self.Display, 1)

but nowadays, you can achieve the same effect with:
command = functtools.partial(self.Display,1)

or, much clearer for non-guru programmers, and a lot easier to extend
when you realize that you have to do more than just calling a single
method, use a local callback function:

def do_display():
self.Display(1)

w = Button(callback=do_display)

local functions are cheap in Python; creating a new one for each button
is very inexpensive.

for very simple callbacks, you can use the lambda syntax as well:

w = Button(callback=lambda: self.Display(1))

</F>
 
S

skanemupp

def __init__(self):
# ...
button = Button(self,
text='1',
command=lambda n=1: self.display(n))
# ...

def display(self, number):
print number


should this really be inside the __init__ function?
 
S

skanemupp

what's wrong with creating widgets in an __init__ method?

</F>


i dont know, i used a piece of code i found which had a createwidgets-
method. isnt init a function, not a method btw(or it is the same
thing?)




this is the current code, only included 2 buttons here to make it
shorter. i might still have misinterpreted though, is the code
correct(it runs correct at least...)?
whats the advantage/disadvante to have it inside the init?


#! /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.btnDisplay = Button(self,text='1',command=lambda
n=1:self.Display(n))
self.btnDisplay.grid(row=3, column=0, padx=5, pady=5)

self.btnDisplay = Button(self,text='/',command=lambda
n="/":self.Display(n))
self.btnDisplay.grid(row=6, column=3, padx=5, pady=5)

def Display(self, number):
print number

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

Advertisements

F

Fredrik Lundh

i dont know, i used a piece of code i found which had a createwidgets-
method. isnt init a function, not a method btw(or it is the same
thing?)

a method is a function defined inside a class statement, and which is
designed to be called via an instance of that class.

def function():
print "this is a function"

def Class:
def method(self):
print "this is a method"

function() # calls a function

obj = Class() # create an instance (call __init__ if present)
obj.method() # calls a method

__init__ is automatically called when Python creates a new instance.

if you create the widgets inside the init method or inside a separate
method that's called from the init method (or from the outside) is up
to you.

</F>
 
7

7stud

am i not doing that then? did u look at the code? where do i add the
bind if this:
btnDisplay = Button(self, text="1", command=self.Display)
        btnDisplay.grid(row=3, column=0, padx=5, pady=5)

is not enough?

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

        if text=="1":
            print 1

i get this exception so i need to pass another argument? im passing 2
no?

1) Post the line in your code that passes two arguments to Display.

2) Post the line in yoru code where you call Display. "call" means
"execute", and '()' is used after a function name to execute the
function.
 
Ad

Advertisements

S

skanemupp

it works now. here is all the 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):

## """Create the Entry, set it to be a bit wider"""
## self.enText = Entry(self)
## self.enText.grid(row=0, column=0, columnspan=3)

"""Create the Button, set the text and the
command that will be called when the button is clicked"""
self.btnDisplay = Button(self, text="calculate!",
state=DISABLED)
self.btnDisplay.grid(row=0, column=31)


self.btnDisplay = Button(self,text='1',command=lambda
n=1:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=3, column=0, padx=5, pady=5)

self.btnDisplay = Button(self,text='2',command=lambda
n=2:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=3, column=1, padx=5, pady=5)

self.btnDisplay = Button(self,text='3',command=lambda
n=3:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=3, column=2, padx=5, pady=5)

self.btnDisplay = Button(self,text='+',command=lambda
n="+":self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=3, column=3, padx=5, pady=5)

self.btnDisplay = Button(self,text='4',command=lambda
n=4:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=4, column=0, padx=5, pady=5)

self.btnDisplay = Button(self,text='5',command=lambda
n=5:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=4, column=1, padx=5, pady=5)

self.btnDisplay = Button(self,text='6',command=lambda
n=6:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=4, column=2, padx=5, pady=5)

self.btnDisplay = Button(self,text='-',command=lambda
n="-":self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=4, column=3, padx=5, pady=5)

self.btnDisplay = Button(self,text='7',command=lambda
n=7:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=5, column=0, padx=5, pady=5)

self.btnDisplay = Button(self,text='8',command=lambda
n=8:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=5, column=1, padx=5, pady=5)

self.btnDisplay = Button(self,text='9',command=lambda
n=9:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=5, column=2, padx=5, pady=5)

self.btnDisplay = Button(self,text='*',command=lambda
n="*":self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=5, column=3, padx=5, pady=5)

self.btnDisplay = Button(self,text='0',command=lambda
n=0:self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=6, column=0, padx=5, pady=5)

self.btnDisplay = Button(self,text='C',command=lambda
n="C":self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=6, column=1, padx=5, pady=5)

self.btnDisplay = Button(self,text='r',command=lambda
n="r":self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=6, column=2, padx=5, pady=5)

self.btnDisplay = Button(self,text='/',command=lambda
n="/":self.Display(n),width=1,height=1)
self.btnDisplay.grid(row=6, column=3, padx=5, pady=5)




def Display(self, number):
#print number
self.lbText = Label(self, text=number)
self.lbText.grid(row=0, column=0)



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

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top