[Pythonmac-SIG] Buttons in W
Corran Webster
cwebster@nevada.edu
Fri, 23 Mar 2001 11:22:23 -0800
At 5:44 PM +0100 23/3/01, Fran=E7ois Granger wrote:
>This is my first attempt at using the W module.
If you haven't already discovered it, you may find my tutorial on W usefu=
l:
http://www.nevada.edu/~cwebster/Python/WWidgets/index.html
In particular, you may find some of the tricks used in the calculator=20
example to be helpful, as there are some common features with what=20
you want to do:
http://www.nevada.edu/~cwebster/Python/WWidgets/calculator.html
>As an exercise, I am trying to program the game "TicTacToe".
>
>My idea is to do a set of identical buttons in 3 row by three=20
>column. My problem is to write a call back function for all these=20
>button wich can detect wich one was clicked.
>
>some ugly code below, thanks for any input.
[snip]
>Token =3D 'O'
>def bpCase():
> """
> handle the click on one location
> """
> for i in range(3):
> for j in range(3):
> # here i need to get i,j when that is the=20
>button just clicked.
> print w[i, j]._activated
> if w[i, j]._activated:
> print i,j
> b =3D i,j
> # here i will use b for other purposes
> w[b]._title =3D token
Your problem seems to be determining which button was clicked from=20
within the callback. Probably the easiest way to deal with this is=20
to do the following:
def bpCase(i, j):
global Token
button =3D w[i,j]
# do stuff with button:
button.settitle(Token) # show either "X" or "O"
button.enable(0) # make the button unclickable from now on
# do stuff related to the game
if Token =3D=3D "X":
Token =3D "O"
else:
Token =3D "X"
# some code to determine if we have a winner - maybe calling out to =
a
# class holding game state or a function which checks for wins or dr=
aws.
# You'll need to write this.
You then need to use a lambda with default arguments which calls=20
bpCase for your callback for each button:
>stepb =3D 16
>for i in range(3):
> for j in range(3):
> w[i,j] =3D W.Button((20 + i * stepb,20 + j *=20
>stepb,stepb,stepb), "X", bpCase)
The creation line then looks something like:
w[i,j] =3D W.Button((20 + i * stepb,20 + j * stepb,stepb=
,stepb),
"", lambda i=3Di, j=3Dj: bpCase(i,j))
Notice the magic "lambda i=3Di, j=3Dj: bpCase(i,j)" which makes the=20
callback know which button it is associated with.
As written, the above code allows two humans to play, but doesn't=20
determine a winner. Once a button is clicked, it is disabled and is=20
greyed out. A slightly better approach would be the following:
def bpCase(i, j):
global Token
button =3D w[i,j]
# do stuff with button:
if button.gettitle():
return
button.settitle(Token) # show either "X" or "O"
# do stuff related to the game
if Token =3D=3D "X":
Token =3D "O"
else:
Token =3D "X"
# some code to determine if we have a winner - maybe calling out to =
a
# class holding game state or a function which checks for wins or dr=
aws.
# You'll need to write this.
A more elegant solution would probably be to subclass W.Button,=20
rather than using callbacks. You would override the click() (and=20
possibly the push()) methods to do what you would normally do in the=20
callback, but now you don't have to worry about finding your button,=20
as it is available as "self". This also allows a more elegent=20
solution to the disabling of the button - simply ignore clicks are=20
the state has been set.
Regards,
Corran