| | |
Tkinter Button(s)
Please support our Python advertiser: Programming Forums - DaniWeb Sister Site
Thread Solved |
I have addressed this problem sometime ago; I have either misplaced, misunderstood, or never received a response to this issue so therefore I am again attempting to deal with a Python issue:
I am towards the end of a build, and I am dealing with button commands, something that was not necessary to finalize in the program until this point. I need to either:
sharky_machine
I am towards the end of a build, and I am dealing with button commands, something that was not necessary to finalize in the program until this point. I need to either:
- Code one button widget to allow multiple command arguments, that is, the same button is capable of issuing unique event commands at different points
- Or, I need to be able to destroy or delete the said button so I am able to reload and redisplay it bound to a single, unique command (example: only one button is seemingly displayed from the user's point-of-view, but it is actually 3, seperate "buttons" that perform 3, unique command events.) This does not seem to be the method to use, but unless I can determine a cleaner method such as one button with multiple command references allowed, I see no other way at this point.
sharky_machine
•
•
Join Date: Jul 2006
Posts: 608
Reputation:
Solved Threads: 150
well, one approach could be to have the button attached to a single callback that checks state and calls one of three functions based on the state:
commands is then a jump table that gets you to the right function.
You could lambda-ize that solution as well, like this:
But that latter solution won't work if the callback has to extract info from self in order to find out which function to call.
Jeff
Python Syntax (Toggle Plain Text)
def callback(self): commands = [self.myfunc1, self.myfunc2, self.myfunc3] commands[self.mydata]()
You could lambda-ize that solution as well, like this:
Python Syntax (Toggle Plain Text)
self.commands = [self.myfunc1, self.myfunc2, self.myfunc3] self.b = Button(self, ..., command=lambda :self.commands[self.mydata]())
Jeff
•
•
•
•
well, one approach could be to have the button attached to a single callback that checks state and calls one of three functions based on the state:
commands is then a jump table that gets you to the right function.Python Syntax (Toggle Plain Text)
def callback(self): commands = [self.myfunc1, self.myfunc2, self.myfunc3] commands[self.mydata]()
You could lambda-ize that solution as well, like this:
But that latter solution won't work if the callback has to extract info from self in order to find out which function to call.Python Syntax (Toggle Plain Text)
self.commands = [self.myfunc1, self.myfunc2, self.myfunc3] self.b = Button(self, ..., command=lambda :self.commands[self.mydata]())
Jeff
•
•
•
•
I have addressed this problem sometime ago; I have either misplaced, misunderstood, or never received a response to this issue so therefore I am again attempting to deal with a Python issue:
I am towards the end of a build, and I am dealing with button commands, something that was not necessary to finalize in the program until this point. I need to either:~Thank-you in advance for any responses\ ideas
- Code one button widget to allow multiple command arguments, that is, the same button is capable of issuing unique event commands at different points
- Or, I need to be able to destroy or delete the said button so I am able to reload and redisplay it bound to a single, unique command (example: only one button is seemingly displayed from the user's point-of-view, but it is actually 3, seperate "buttons" that perform 3, unique command events.) This does not seem to be the method to use, but unless I can determine a cleaner method such as one button with multiple command references allowed, I see no other way at this point.
sharky_machine
I have been trying the given suggestions as well as other, possible options researched online; I was able to solve my initial problem concerning "command=" but it displays two (2) buttons instead of a single button -- I require only one button at all times. I am obviously missing something here.
I have tried various things such as: destroy, delete, forget-- in order to get rid of the first displayed button and replace it visibly with the second. One button to harbor a few commands. Right now at this point the program in general is running bug-free, smooth, and fast-- then I reach the post-load where I will require user input more than once via this one, aforementioned button. Below is the button code as it stands:
Python Syntax (Toggle Plain Text)
image00 = PhotoImage(file='grey1.gif') btn1 = Button(root ,bg="Black", text="HIT", image=image00,command=show_image2) btn1. pack() btn1 = Button(root ,bg="Black", text="HIT", image=image00,command=show_image3) btn1. pack() def button_command(): command=show_image2() command=show_image3() btn1 = Button(root ,bg="Black", text="HIT", image=image00) def switch(): pack.forget() button2.pack()
Thank-you in advance.
sharky_machine
•
•
Join Date: Jul 2006
Posts: 608
Reputation:
Solved Threads: 150
I believe that what is happening is that btn1 is being set to the first instance of Button, which is then packed (I prefer 'grid', BTW). Then btn1 is set to the second instance of Button, which is also packed. The reference to the first Button is then lost; your code has no way of accessing it, even though Tk continues to maintain a reference to it on its parent frame.
I don't know why pack.forget() doesn't fix that problem.
But if I understand your intent correctly, you want to switch out the button text and image, but not the button itself, yes?
One possibility is to use a textvariable for the Button rather than static text. It might also be possible to change the image on the fly.
See http://infohost.nmt.edu/tcc/help/pubs/tkinter.pdf for info on using textvariable.
Sorry for the partial solution; hope it helps.
Jeff
I don't know why pack.forget() doesn't fix that problem.
But if I understand your intent correctly, you want to switch out the button text and image, but not the button itself, yes?
One possibility is to use a textvariable for the Button rather than static text. It might also be possible to change the image on the fly.
See http://infohost.nmt.edu/tcc/help/pubs/tkinter.pdf for info on using textvariable.
Sorry for the partial solution; hope it helps.
Jeff
•
•
•
•
I believe that what is happening is that btn1 is being set to the first instance of Button, which is then packed (I prefer 'grid', BTW). Then btn1 is set to the second instance of Button, which is also packed. The reference to the first Button is then lost; your code has no way of accessing it, even though Tk continues to maintain a reference to it on its parent frame.
I don't know why pack.forget() doesn't fix that problem.
But if I understand your intent correctly, you want to switch out the button text and image, but not the button itself, yes?
One possibility is to use a textvariable for the Button rather than static text. It might also be possible to change the image on the fly.
See http://infohost.nmt.edu/tcc/help/pubs/tkinter.pdf for info on using textvariable.
Sorry for the partial solution; hope it helps.
Jeff
Thank-you for your reply.
Let me talk about the needed button function(s) again:
I am towards the tail-end of a GUI Python game build based on Blackjack. I am using Tkinter as my primary graphics module. The build is going very well and I believe it is almost complete (save for testing\ debugging) but I am at a point where I must finish the user input device (the button used to simply allow the player to "HIT" for another card).
This button will be visually, to the user, "one button", that is, they at all times (when the "HIT" button is made available to them to use) will see something like this: [HIT]
*This is actually a pretty, damaged-metal, GIF-fronted button, not just text. No standard keyboard text will be displayed on this button or changed for any reason.
What does this button exactly do? Allows the player to request additional cards. How many cards? At this point (based on statistical studies I've conducted with decks of real playing cards to see how many cards on average allow one to reach "21" without going over) the player can request three (3) new cards via this button (after receiving two computer "dealt" cards) for a total of five (5) cards displayed for their hand. (I determined that, on average, 5 cards generally achieve "21" without going over "21")
I need this one button to allow a player to request a total of 3 new cards. This seems simple but I'm finding (possibly due to my coding design of logic and variables) this is more difficult than I first believed. I am very used to Visual Basic and I initially assumed I would activate buttons in a similar and easy way. Well, I am struggling with this and do not know why.
I figured as a work-around I could have the same [HIT] with single function displayed 3-times without the player noticing-- no screen flash-- just a refresh of the GIF but with a different, seperate line of code imbedded in the background.
I just need to have one instance of this button allowing 3 "commands" which I cannot, it seems.
I'm not sure what I'm doing wrong. I've tried many things: so far, I only get 3 seperate [HIT] buttons displayed at once-- they all work great... but I only need one to be displayed.
Thanks again for your help.
Regards,
sharky_machine
•
•
Join Date: Jul 2006
Posts: 608
Reputation:
Solved Threads: 150
The game sounds really cool. See if this is what you're after:
[php]
from Tkinter import *
import random
class MyFrame(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.buttons = [Button(self, text="1", command=self.switch), \
Button(self, text="2", command=self.switch), \
Button(self, text="3", command=self.switch)]
self.b = random.choice(self.buttons)
self.b.grid()
self.grid()
def switch(self):
self.b.grid_remove()
self.b = random.choice(self.buttons)
self.b.grid()
mainw = Tk()
mainw.frame = MyFrame(mainw)
mainw.mainloop()
[/php]
This allows the user to randomly switch amongst three different buttons. Yours wouldn't be random, of course.
So about the game: if the user hits the button, he gets three cards automatically? I was at first picturing the user hitting the 'Hit' button as many times as he might want, until he busts or wins. But from your description, I'm not sure.
Jeff
[php]
from Tkinter import *
import random
class MyFrame(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.buttons = [Button(self, text="1", command=self.switch), \
Button(self, text="2", command=self.switch), \
Button(self, text="3", command=self.switch)]
self.b = random.choice(self.buttons)
self.b.grid()
self.grid()
def switch(self):
self.b.grid_remove()
self.b = random.choice(self.buttons)
self.b.grid()
mainw = Tk()
mainw.frame = MyFrame(mainw)
mainw.mainloop()
[/php]
This allows the user to randomly switch amongst three different buttons. Yours wouldn't be random, of course.
So about the game: if the user hits the button, he gets three cards automatically? I was at first picturing the user hitting the 'Hit' button as many times as he might want, until he busts or wins. But from your description, I'm not sure.
Jeff
•
•
•
•
The game sounds really cool. See if this is what you're after:
[php]
from Tkinter import *
import random
class MyFrame(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.buttons = [Button(self, text="1", command=self.switch), \
Button(self, text="2", command=self.switch), \
Button(self, text="3", command=self.switch)]
self.b = random.choice(self.buttons)
self.b.grid()
self.grid()
def switch(self):
self.b.grid_remove()
self.b = random.choice(self.buttons)
self.b.grid()
mainw = Tk()
mainw.frame = MyFrame(mainw)
mainw.mainloop()
[/php]
This allows the user to randomly switch amongst three different buttons. Yours wouldn't be random, of course.
So about the game: if the user hits the button, he gets three cards automatically? I was at first picturing the user hitting the 'Hit' button as many times as he might want, until he busts or wins. But from your description, I'm not sure.
Jeff
Thanks for the code-- I will try this out today.
About the button and player use: The player may request up to three cards if they need or choose to do so. Mathematically, they may not need of want to get any additional card(s) beyond the first two cards. Say, for example, one is a King\ face card (10) + the second card (both of these two dealt automatically by the machine) , an Ace (which could be a "1" OR an "11", depending on the other card). This is "21", a natural Blackjack.
They can now choose up to three more cards if they wish (or none) for a TOTAL of five, displayed cards. The computer opponent the "dealer" also may have up to five, total cards. So, the button will allow the user\ human player to "HIT" for three additional cards if they wish to. These three, requested cards would require three, seperate pushes of the said button by the player-- one card per push. One card at a time.
I hope this makes sense. I may not be explaining it well. It is, at first glance, a simple game, but I think it is visually beautiful (GUI and theme of the game) and the logic is a bit more complex than I expected; that is, in order for the computer to read, record, compute, and make decisions as an artificial player, it reacts based on the human player's decisions, that is, the machine must react accordingly so it does not lose as the "Dealer".
The Casino "House" (the computer) should always win, theoretically. :cheesy:
Its quite exciting building this as a personal side project and I will post the game here as a zipped file when complete.
Regards,
Matty D.
Last edited by mattyd; Dec 16th, 2006 at 4:16 pm. Reason: grammer
•
•
•
•
I have addressed this problem sometime ago; I have either misplaced, misunderstood, or never received a response to this issue so therefore I am again attempting to deal with a Python issue:
I am towards the end of a build, and I am dealing with button commands, something that was not necessary to finalize in the program until this point. I need to either:~Thank-you in advance for any responses\ ideas
- Code one button widget to allow multiple command arguments, that is, the same button is capable of issuing unique event commands at different points
- Or, I need to be able to destroy or delete the said button so I am able to reload and redisplay it bound to a single, unique command (example: only one button is seemingly displayed from the user's point-of-view, but it is actually 3, seperate "buttons" that perform 3, unique command events.) This does not seem to be the method to use, but unless I can determine a cleaner method such as one button with multiple command references allowed, I see no other way at this point.
sharky_machine
For example:
Python Syntax (Toggle Plain Text)
def button_command(): command=show_image2() btn1 = Button(root ,bg="Black", text="HIT", image=image00) def switch(): button2.pack() pack.forget()
Regards,
sharky_machine
Last edited by mattyd; Dec 17th, 2006 at 8:56 pm. Reason: [code edit]
Just a thought, I have used that trick before. You can use
to move the object you created right off the canvas to hide it. Then bring it or another object back.
Python Syntax (Toggle Plain Text)
canvas.move(canvas_object, xAmount, yAmount) root.update()
May 'the Google' be with you!
![]() |
Similar Threads
- Tkinter Button Command (Python)
- Tkinter Button "Disable" ? (Python)
Other Threads in the Python Forum
- Previous Thread: Memory usage -- opinions?
- Next Thread: Extending A Class
| Thread Tools | Search this Thread |
address anydbm app beginner changecolor cipher class conversion coordinates corners curves definedlines development dictionary dynamic events examples excel feet file float font format ftp function generator getvalue gui handling homework images import input ip java keycontrol line linux list lists loan loop maintain matching maze millimeter mouse mysqldb number numbers output parsing path permissions port prime programming projects py2exe pygame pymailer python queue random rational raw_input recursion recursive scrolledtext searchingfile shebang slicenotation split string strings table terminal text thread threading time tkinter tlapse tooltip tuple tutorial type ubuntu unicode url urllib urllib2 variable variables vigenere web windows wx.wizard wxpython xlwt






