Binding a keyboard key to a Tkinter button

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I'm specifically asking about binding a keyboard keystroke to a button in a GUI. Originally I planned to bind the keystroke to the GUI button itself, but that seemed impossible, and potentially unwise after I considered it later.
Is this the proper (pythonic) way to bind a keyboard key and GUI button?
## start.py
print 'start'
#from tkinter import *
from Tkinter import *
import os
from PIL import ImageTk, Image
class MyClass:
'''This is my class.'''
imgpath = '/Users/user/Dropbox/Camera Uploads'
imgfile = 'susshi.jpg'
#imgfilepath = os.path.join(self.imgpath, self.imgfile)
imgfilepath = os.path.join(imgpath, imgfile)
def __init__(self,master):
print 'in __init__'
# Create and load a frame into the tk (tkinter) window.
frame = Frame(master)
frame.pack()
# Create and load two buttons in to the above-created frame.
self.button = Button(frame, text="QUIT", fg="red", command=quit)
self.button.pack(side=LEFT)
self.slogan = Button(frame, text="Hello", command = self.f)
self.slogan.pack(side=RIGHT)
# Bind a key to each button from above.
master.bind('q', quit)
master.bind('f', self.f)
# Open the image, resize it...
self.image = Image.open(self.imgfilepath)
self.image.thumbnail((600,600))
# Make a tkinter-friendly image object ...
self.display_image = ImageTk.PhotoImage(self.image)
# Make a tkinter canvas, plug in the image, and pack the canvas.
self.canvas = Canvas(master, bg='red')
self.canvas.create_image(0,0, image=self.display_image, anchor="nw")
self.canvas.pack(fill=BOTH, expand=1)
### FIXME: Set canvas focus!
def f(self, event=None):
print 'in f()'
return 'hello world'
def get_image_list(self):
pass
def next_image(self):
pass
def previous_image(self):
pass
def load_image(self):
#stub
pass
def update_image(self):
pass
root = Tk()
abc = MyClass(root)
root.mainloop()
print 'abc has been defined'
print '"abc.f()" returns "%s"' % abc.f()
#print str(abc.f)
#print repr(abc.f)
print 'end'
The intention of the project is to make a simple image viewer in python, with buttons in the GUI for basic navigation functions, and keys mapped to those same functions.
python python-2.7 event-handling tkinter
 |Â
show 1 more comment
up vote
4
down vote
favorite
I'm specifically asking about binding a keyboard keystroke to a button in a GUI. Originally I planned to bind the keystroke to the GUI button itself, but that seemed impossible, and potentially unwise after I considered it later.
Is this the proper (pythonic) way to bind a keyboard key and GUI button?
## start.py
print 'start'
#from tkinter import *
from Tkinter import *
import os
from PIL import ImageTk, Image
class MyClass:
'''This is my class.'''
imgpath = '/Users/user/Dropbox/Camera Uploads'
imgfile = 'susshi.jpg'
#imgfilepath = os.path.join(self.imgpath, self.imgfile)
imgfilepath = os.path.join(imgpath, imgfile)
def __init__(self,master):
print 'in __init__'
# Create and load a frame into the tk (tkinter) window.
frame = Frame(master)
frame.pack()
# Create and load two buttons in to the above-created frame.
self.button = Button(frame, text="QUIT", fg="red", command=quit)
self.button.pack(side=LEFT)
self.slogan = Button(frame, text="Hello", command = self.f)
self.slogan.pack(side=RIGHT)
# Bind a key to each button from above.
master.bind('q', quit)
master.bind('f', self.f)
# Open the image, resize it...
self.image = Image.open(self.imgfilepath)
self.image.thumbnail((600,600))
# Make a tkinter-friendly image object ...
self.display_image = ImageTk.PhotoImage(self.image)
# Make a tkinter canvas, plug in the image, and pack the canvas.
self.canvas = Canvas(master, bg='red')
self.canvas.create_image(0,0, image=self.display_image, anchor="nw")
self.canvas.pack(fill=BOTH, expand=1)
### FIXME: Set canvas focus!
def f(self, event=None):
print 'in f()'
return 'hello world'
def get_image_list(self):
pass
def next_image(self):
pass
def previous_image(self):
pass
def load_image(self):
#stub
pass
def update_image(self):
pass
root = Tk()
abc = MyClass(root)
root.mainloop()
print 'abc has been defined'
print '"abc.f()" returns "%s"' % abc.f()
#print str(abc.f)
#print repr(abc.f)
print 'end'
The intention of the project is to make a simple image viewer in python, with buttons in the GUI for basic navigation functions, and keys mapped to those same functions.
python python-2.7 event-handling tkinter
This is the actual code I'm using. I haven't implemented the other functions yet, and I was hoping to just get the code implemented thus-far reviewed. In fact, the original question was just asking about reviewing one specific portion of the code - that is, the binding of the keystrokes in association with the buttons in the GUI. However, that specific-level of question was downvoted and given a recommendation to adhere to the guidance in the help center. I understand there may be a common issue of incomplete code segments posted, but I have truly included the entire module.
â user3.1415927
Apr 7 at 15:03
This question has been brought to attention on meta.
â Simon Forsbergâ¦
Apr 7 at 15:53
On the last edit: There really isn't a GUI-agnostic way to ask this question. Each library will have its own way of handling button binding. An answer in PyQT would be useless for tkinter.
â Steven Vascellaro
May 1 at 15:39
@StevenVascellaro interesting, I am unfamiliar with any other GUI options for python. In fact, I'd be open to suggestions with those other frameworks, if they are also pythonic - hence the leaving of the wording. Although I do understand the wording change suggestion (since my code was already using tkinter), I'd be open to the correction I see from time to time on SE of: 'Yes, it will work this way, but a better way is to XYZ.' I'm here to learn! :)
â user3.1415927
May 1 at 15:42
@user3.1415927 I'm using tkinter myself, but PyQT is a popular alternative. (See Graphic User Interface FAQ)
â Steven Vascellaro
May 1 at 15:45
 |Â
show 1 more comment
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I'm specifically asking about binding a keyboard keystroke to a button in a GUI. Originally I planned to bind the keystroke to the GUI button itself, but that seemed impossible, and potentially unwise after I considered it later.
Is this the proper (pythonic) way to bind a keyboard key and GUI button?
## start.py
print 'start'
#from tkinter import *
from Tkinter import *
import os
from PIL import ImageTk, Image
class MyClass:
'''This is my class.'''
imgpath = '/Users/user/Dropbox/Camera Uploads'
imgfile = 'susshi.jpg'
#imgfilepath = os.path.join(self.imgpath, self.imgfile)
imgfilepath = os.path.join(imgpath, imgfile)
def __init__(self,master):
print 'in __init__'
# Create and load a frame into the tk (tkinter) window.
frame = Frame(master)
frame.pack()
# Create and load two buttons in to the above-created frame.
self.button = Button(frame, text="QUIT", fg="red", command=quit)
self.button.pack(side=LEFT)
self.slogan = Button(frame, text="Hello", command = self.f)
self.slogan.pack(side=RIGHT)
# Bind a key to each button from above.
master.bind('q', quit)
master.bind('f', self.f)
# Open the image, resize it...
self.image = Image.open(self.imgfilepath)
self.image.thumbnail((600,600))
# Make a tkinter-friendly image object ...
self.display_image = ImageTk.PhotoImage(self.image)
# Make a tkinter canvas, plug in the image, and pack the canvas.
self.canvas = Canvas(master, bg='red')
self.canvas.create_image(0,0, image=self.display_image, anchor="nw")
self.canvas.pack(fill=BOTH, expand=1)
### FIXME: Set canvas focus!
def f(self, event=None):
print 'in f()'
return 'hello world'
def get_image_list(self):
pass
def next_image(self):
pass
def previous_image(self):
pass
def load_image(self):
#stub
pass
def update_image(self):
pass
root = Tk()
abc = MyClass(root)
root.mainloop()
print 'abc has been defined'
print '"abc.f()" returns "%s"' % abc.f()
#print str(abc.f)
#print repr(abc.f)
print 'end'
The intention of the project is to make a simple image viewer in python, with buttons in the GUI for basic navigation functions, and keys mapped to those same functions.
python python-2.7 event-handling tkinter
I'm specifically asking about binding a keyboard keystroke to a button in a GUI. Originally I planned to bind the keystroke to the GUI button itself, but that seemed impossible, and potentially unwise after I considered it later.
Is this the proper (pythonic) way to bind a keyboard key and GUI button?
## start.py
print 'start'
#from tkinter import *
from Tkinter import *
import os
from PIL import ImageTk, Image
class MyClass:
'''This is my class.'''
imgpath = '/Users/user/Dropbox/Camera Uploads'
imgfile = 'susshi.jpg'
#imgfilepath = os.path.join(self.imgpath, self.imgfile)
imgfilepath = os.path.join(imgpath, imgfile)
def __init__(self,master):
print 'in __init__'
# Create and load a frame into the tk (tkinter) window.
frame = Frame(master)
frame.pack()
# Create and load two buttons in to the above-created frame.
self.button = Button(frame, text="QUIT", fg="red", command=quit)
self.button.pack(side=LEFT)
self.slogan = Button(frame, text="Hello", command = self.f)
self.slogan.pack(side=RIGHT)
# Bind a key to each button from above.
master.bind('q', quit)
master.bind('f', self.f)
# Open the image, resize it...
self.image = Image.open(self.imgfilepath)
self.image.thumbnail((600,600))
# Make a tkinter-friendly image object ...
self.display_image = ImageTk.PhotoImage(self.image)
# Make a tkinter canvas, plug in the image, and pack the canvas.
self.canvas = Canvas(master, bg='red')
self.canvas.create_image(0,0, image=self.display_image, anchor="nw")
self.canvas.pack(fill=BOTH, expand=1)
### FIXME: Set canvas focus!
def f(self, event=None):
print 'in f()'
return 'hello world'
def get_image_list(self):
pass
def next_image(self):
pass
def previous_image(self):
pass
def load_image(self):
#stub
pass
def update_image(self):
pass
root = Tk()
abc = MyClass(root)
root.mainloop()
print 'abc has been defined'
print '"abc.f()" returns "%s"' % abc.f()
#print str(abc.f)
#print repr(abc.f)
print 'end'
The intention of the project is to make a simple image viewer in python, with buttons in the GUI for basic navigation functions, and keys mapped to those same functions.
python python-2.7 event-handling tkinter
edited May 1 at 15:33
asked Apr 7 at 14:09
user3.1415927
264
264
This is the actual code I'm using. I haven't implemented the other functions yet, and I was hoping to just get the code implemented thus-far reviewed. In fact, the original question was just asking about reviewing one specific portion of the code - that is, the binding of the keystrokes in association with the buttons in the GUI. However, that specific-level of question was downvoted and given a recommendation to adhere to the guidance in the help center. I understand there may be a common issue of incomplete code segments posted, but I have truly included the entire module.
â user3.1415927
Apr 7 at 15:03
This question has been brought to attention on meta.
â Simon Forsbergâ¦
Apr 7 at 15:53
On the last edit: There really isn't a GUI-agnostic way to ask this question. Each library will have its own way of handling button binding. An answer in PyQT would be useless for tkinter.
â Steven Vascellaro
May 1 at 15:39
@StevenVascellaro interesting, I am unfamiliar with any other GUI options for python. In fact, I'd be open to suggestions with those other frameworks, if they are also pythonic - hence the leaving of the wording. Although I do understand the wording change suggestion (since my code was already using tkinter), I'd be open to the correction I see from time to time on SE of: 'Yes, it will work this way, but a better way is to XYZ.' I'm here to learn! :)
â user3.1415927
May 1 at 15:42
@user3.1415927 I'm using tkinter myself, but PyQT is a popular alternative. (See Graphic User Interface FAQ)
â Steven Vascellaro
May 1 at 15:45
 |Â
show 1 more comment
This is the actual code I'm using. I haven't implemented the other functions yet, and I was hoping to just get the code implemented thus-far reviewed. In fact, the original question was just asking about reviewing one specific portion of the code - that is, the binding of the keystrokes in association with the buttons in the GUI. However, that specific-level of question was downvoted and given a recommendation to adhere to the guidance in the help center. I understand there may be a common issue of incomplete code segments posted, but I have truly included the entire module.
â user3.1415927
Apr 7 at 15:03
This question has been brought to attention on meta.
â Simon Forsbergâ¦
Apr 7 at 15:53
On the last edit: There really isn't a GUI-agnostic way to ask this question. Each library will have its own way of handling button binding. An answer in PyQT would be useless for tkinter.
â Steven Vascellaro
May 1 at 15:39
@StevenVascellaro interesting, I am unfamiliar with any other GUI options for python. In fact, I'd be open to suggestions with those other frameworks, if they are also pythonic - hence the leaving of the wording. Although I do understand the wording change suggestion (since my code was already using tkinter), I'd be open to the correction I see from time to time on SE of: 'Yes, it will work this way, but a better way is to XYZ.' I'm here to learn! :)
â user3.1415927
May 1 at 15:42
@user3.1415927 I'm using tkinter myself, but PyQT is a popular alternative. (See Graphic User Interface FAQ)
â Steven Vascellaro
May 1 at 15:45
This is the actual code I'm using. I haven't implemented the other functions yet, and I was hoping to just get the code implemented thus-far reviewed. In fact, the original question was just asking about reviewing one specific portion of the code - that is, the binding of the keystrokes in association with the buttons in the GUI. However, that specific-level of question was downvoted and given a recommendation to adhere to the guidance in the help center. I understand there may be a common issue of incomplete code segments posted, but I have truly included the entire module.
â user3.1415927
Apr 7 at 15:03
This is the actual code I'm using. I haven't implemented the other functions yet, and I was hoping to just get the code implemented thus-far reviewed. In fact, the original question was just asking about reviewing one specific portion of the code - that is, the binding of the keystrokes in association with the buttons in the GUI. However, that specific-level of question was downvoted and given a recommendation to adhere to the guidance in the help center. I understand there may be a common issue of incomplete code segments posted, but I have truly included the entire module.
â user3.1415927
Apr 7 at 15:03
This question has been brought to attention on meta.
â Simon Forsbergâ¦
Apr 7 at 15:53
This question has been brought to attention on meta.
â Simon Forsbergâ¦
Apr 7 at 15:53
On the last edit: There really isn't a GUI-agnostic way to ask this question. Each library will have its own way of handling button binding. An answer in PyQT would be useless for tkinter.
â Steven Vascellaro
May 1 at 15:39
On the last edit: There really isn't a GUI-agnostic way to ask this question. Each library will have its own way of handling button binding. An answer in PyQT would be useless for tkinter.
â Steven Vascellaro
May 1 at 15:39
@StevenVascellaro interesting, I am unfamiliar with any other GUI options for python. In fact, I'd be open to suggestions with those other frameworks, if they are also pythonic - hence the leaving of the wording. Although I do understand the wording change suggestion (since my code was already using tkinter), I'd be open to the correction I see from time to time on SE of: 'Yes, it will work this way, but a better way is to XYZ.' I'm here to learn! :)
â user3.1415927
May 1 at 15:42
@StevenVascellaro interesting, I am unfamiliar with any other GUI options for python. In fact, I'd be open to suggestions with those other frameworks, if they are also pythonic - hence the leaving of the wording. Although I do understand the wording change suggestion (since my code was already using tkinter), I'd be open to the correction I see from time to time on SE of: 'Yes, it will work this way, but a better way is to XYZ.' I'm here to learn! :)
â user3.1415927
May 1 at 15:42
@user3.1415927 I'm using tkinter myself, but PyQT is a popular alternative. (See Graphic User Interface FAQ)
â Steven Vascellaro
May 1 at 15:45
@user3.1415927 I'm using tkinter myself, but PyQT is a popular alternative. (See Graphic User Interface FAQ)
â Steven Vascellaro
May 1 at 15:45
 |Â
show 1 more comment
2 Answers
2
active
oldest
votes
up vote
1
down vote
TL;DR: Yes, binding the keyboard key and button to the same function is a proper solution.
How to bind a keyboard key to a tkinter button
There are two ways to share a function between a bind keypress a command button.
Method 1: Use an optional event parameter
As you have already discovered yourself, you can use an optional event parameter that you don't depend on.
Since the parameter is unused, you can prefix it with an underscore (_event) to prevent warnings.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
root = Tk()
abc = MyClass(root)
root.mainloop()
Method 2: Use lambdas
If the event parameter isn't being used, you can discard it by binding your key to a lambda function.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world!")
root = Tk()
abc = MyClass(root)
root.mainloop()
(See How do I make Bind and Command do the same thing in tkinter?)
Miscellaneous tips
Avoid using wildcard imports
You should try to be explicit whenever you import in Python.
Yes
from Tkinter import Tk, Button, Frame
Yes
import Tkinter as tk
No
from Tkinter import *
(See Why is âÂÂimport *â bad?)
Switch to Python 3
As coal_'s answer mentioned, development on Python 2 is scheduled to end in 2020. To ensure continued support, you should transition to Python 3 or later.
Use strings when packing constants
This is more personal preference than a rule, but I usually try to use strings when packing in tkinter. It means you don't have to import as many things.
Yes
self.button.pack(side="left")
No
self.button.pack(side=LEFT)
Unused variables are typically named_. Prefixing a name with an underscore is usually done to distinguish 'private' names from 'public' names (those listed in__all__, or at least those part of the API).
â Daniel
May 1 at 15:33
@Coal_ I remember seeing unused_arguments suggested as a PEP proposal. Was that proposal ever approved?
â Steven Vascellaro
May 1 at 15:37
As a PEP on its own? I'm looking through the list of PEPs now, but can't find it.
â Daniel
May 1 at 15:56
1
I may have been mistaken about PEP. IâÂÂve found there isnâÂÂt much consensus on how to name unused arguments, but Pylint favors descriptive names prefixed with underscore.
â Steven Vascellaro
May 1 at 16:00
add a comment |Â
up vote
0
down vote
Is this the proper(, pythonic) way to bind a keyboard key and GUI button?
Sure. It's hard to judge exactly what you mean by 'proper', but it works, and I don't see any major caveats with this approach. Binding the callback to the button and calling button.focus_set() works just as well, but your approach makes more sense. Think about it: Does the callback apply only to the button? At least in the case of the quit-callback, no; no matter what widget has focus, pressing 'q' should quit the application.
Some other remarks:
Using wildcard imports (
from <module> import *) is discouraged for a number of reasons. For one, using wildcard imports can cause conflicts if two symbols with the same name, defined in different namespaces, are imported into the global namespace. Secondly, for other developers, there's no way to quickly tell where an object was defined.PEP-8 proposes sorting
importstatements alphabetically.Unless you have compelling reasons to use Python 2, switch to Python 3! Version 2.7 will only be supported until 2020 (see PEP-373).
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
TL;DR: Yes, binding the keyboard key and button to the same function is a proper solution.
How to bind a keyboard key to a tkinter button
There are two ways to share a function between a bind keypress a command button.
Method 1: Use an optional event parameter
As you have already discovered yourself, you can use an optional event parameter that you don't depend on.
Since the parameter is unused, you can prefix it with an underscore (_event) to prevent warnings.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
root = Tk()
abc = MyClass(root)
root.mainloop()
Method 2: Use lambdas
If the event parameter isn't being used, you can discard it by binding your key to a lambda function.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world!")
root = Tk()
abc = MyClass(root)
root.mainloop()
(See How do I make Bind and Command do the same thing in tkinter?)
Miscellaneous tips
Avoid using wildcard imports
You should try to be explicit whenever you import in Python.
Yes
from Tkinter import Tk, Button, Frame
Yes
import Tkinter as tk
No
from Tkinter import *
(See Why is âÂÂimport *â bad?)
Switch to Python 3
As coal_'s answer mentioned, development on Python 2 is scheduled to end in 2020. To ensure continued support, you should transition to Python 3 or later.
Use strings when packing constants
This is more personal preference than a rule, but I usually try to use strings when packing in tkinter. It means you don't have to import as many things.
Yes
self.button.pack(side="left")
No
self.button.pack(side=LEFT)
Unused variables are typically named_. Prefixing a name with an underscore is usually done to distinguish 'private' names from 'public' names (those listed in__all__, or at least those part of the API).
â Daniel
May 1 at 15:33
@Coal_ I remember seeing unused_arguments suggested as a PEP proposal. Was that proposal ever approved?
â Steven Vascellaro
May 1 at 15:37
As a PEP on its own? I'm looking through the list of PEPs now, but can't find it.
â Daniel
May 1 at 15:56
1
I may have been mistaken about PEP. IâÂÂve found there isnâÂÂt much consensus on how to name unused arguments, but Pylint favors descriptive names prefixed with underscore.
â Steven Vascellaro
May 1 at 16:00
add a comment |Â
up vote
1
down vote
TL;DR: Yes, binding the keyboard key and button to the same function is a proper solution.
How to bind a keyboard key to a tkinter button
There are two ways to share a function between a bind keypress a command button.
Method 1: Use an optional event parameter
As you have already discovered yourself, you can use an optional event parameter that you don't depend on.
Since the parameter is unused, you can prefix it with an underscore (_event) to prevent warnings.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
root = Tk()
abc = MyClass(root)
root.mainloop()
Method 2: Use lambdas
If the event parameter isn't being used, you can discard it by binding your key to a lambda function.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world!")
root = Tk()
abc = MyClass(root)
root.mainloop()
(See How do I make Bind and Command do the same thing in tkinter?)
Miscellaneous tips
Avoid using wildcard imports
You should try to be explicit whenever you import in Python.
Yes
from Tkinter import Tk, Button, Frame
Yes
import Tkinter as tk
No
from Tkinter import *
(See Why is âÂÂimport *â bad?)
Switch to Python 3
As coal_'s answer mentioned, development on Python 2 is scheduled to end in 2020. To ensure continued support, you should transition to Python 3 or later.
Use strings when packing constants
This is more personal preference than a rule, but I usually try to use strings when packing in tkinter. It means you don't have to import as many things.
Yes
self.button.pack(side="left")
No
self.button.pack(side=LEFT)
Unused variables are typically named_. Prefixing a name with an underscore is usually done to distinguish 'private' names from 'public' names (those listed in__all__, or at least those part of the API).
â Daniel
May 1 at 15:33
@Coal_ I remember seeing unused_arguments suggested as a PEP proposal. Was that proposal ever approved?
â Steven Vascellaro
May 1 at 15:37
As a PEP on its own? I'm looking through the list of PEPs now, but can't find it.
â Daniel
May 1 at 15:56
1
I may have been mistaken about PEP. IâÂÂve found there isnâÂÂt much consensus on how to name unused arguments, but Pylint favors descriptive names prefixed with underscore.
â Steven Vascellaro
May 1 at 16:00
add a comment |Â
up vote
1
down vote
up vote
1
down vote
TL;DR: Yes, binding the keyboard key and button to the same function is a proper solution.
How to bind a keyboard key to a tkinter button
There are two ways to share a function between a bind keypress a command button.
Method 1: Use an optional event parameter
As you have already discovered yourself, you can use an optional event parameter that you don't depend on.
Since the parameter is unused, you can prefix it with an underscore (_event) to prevent warnings.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
root = Tk()
abc = MyClass(root)
root.mainloop()
Method 2: Use lambdas
If the event parameter isn't being used, you can discard it by binding your key to a lambda function.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world!")
root = Tk()
abc = MyClass(root)
root.mainloop()
(See How do I make Bind and Command do the same thing in tkinter?)
Miscellaneous tips
Avoid using wildcard imports
You should try to be explicit whenever you import in Python.
Yes
from Tkinter import Tk, Button, Frame
Yes
import Tkinter as tk
No
from Tkinter import *
(See Why is âÂÂimport *â bad?)
Switch to Python 3
As coal_'s answer mentioned, development on Python 2 is scheduled to end in 2020. To ensure continued support, you should transition to Python 3 or later.
Use strings when packing constants
This is more personal preference than a rule, but I usually try to use strings when packing in tkinter. It means you don't have to import as many things.
Yes
self.button.pack(side="left")
No
self.button.pack(side=LEFT)
TL;DR: Yes, binding the keyboard key and button to the same function is a proper solution.
How to bind a keyboard key to a tkinter button
There are two ways to share a function between a bind keypress a command button.
Method 1: Use an optional event parameter
As you have already discovered yourself, you can use an optional event parameter that you don't depend on.
Since the parameter is unused, you can prefix it with an underscore (_event) to prevent warnings.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', self.func)
def func(self, _event=None):
print("Hello, world")
root = Tk()
abc = MyClass(root)
root.mainloop()
Method 2: Use lambdas
If the event parameter isn't being used, you can discard it by binding your key to a lambda function.
self.button = Button(frame, text="Hello", command=self.func)
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world")
Full Example:
# from tkinter import Button, Frame, Tk # Python 3
from Tkinter import Button, Frame, Tk # Python 2
class MyClass:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Hello", command=self.func)
self.button.pack(side='left')
master.bind('f', lambda event: self.func())
def func(self):
print("Hello, world!")
root = Tk()
abc = MyClass(root)
root.mainloop()
(See How do I make Bind and Command do the same thing in tkinter?)
Miscellaneous tips
Avoid using wildcard imports
You should try to be explicit whenever you import in Python.
Yes
from Tkinter import Tk, Button, Frame
Yes
import Tkinter as tk
No
from Tkinter import *
(See Why is âÂÂimport *â bad?)
Switch to Python 3
As coal_'s answer mentioned, development on Python 2 is scheduled to end in 2020. To ensure continued support, you should transition to Python 3 or later.
Use strings when packing constants
This is more personal preference than a rule, but I usually try to use strings when packing in tkinter. It means you don't have to import as many things.
Yes
self.button.pack(side="left")
No
self.button.pack(side=LEFT)
edited May 1 at 17:40
answered May 1 at 15:11
Steven Vascellaro
1277
1277
Unused variables are typically named_. Prefixing a name with an underscore is usually done to distinguish 'private' names from 'public' names (those listed in__all__, or at least those part of the API).
â Daniel
May 1 at 15:33
@Coal_ I remember seeing unused_arguments suggested as a PEP proposal. Was that proposal ever approved?
â Steven Vascellaro
May 1 at 15:37
As a PEP on its own? I'm looking through the list of PEPs now, but can't find it.
â Daniel
May 1 at 15:56
1
I may have been mistaken about PEP. IâÂÂve found there isnâÂÂt much consensus on how to name unused arguments, but Pylint favors descriptive names prefixed with underscore.
â Steven Vascellaro
May 1 at 16:00
add a comment |Â
Unused variables are typically named_. Prefixing a name with an underscore is usually done to distinguish 'private' names from 'public' names (those listed in__all__, or at least those part of the API).
â Daniel
May 1 at 15:33
@Coal_ I remember seeing unused_arguments suggested as a PEP proposal. Was that proposal ever approved?
â Steven Vascellaro
May 1 at 15:37
As a PEP on its own? I'm looking through the list of PEPs now, but can't find it.
â Daniel
May 1 at 15:56
1
I may have been mistaken about PEP. IâÂÂve found there isnâÂÂt much consensus on how to name unused arguments, but Pylint favors descriptive names prefixed with underscore.
â Steven Vascellaro
May 1 at 16:00
Unused variables are typically named
_. Prefixing a name with an underscore is usually done to distinguish 'private' names from 'public' names (those listed in __all__, or at least those part of the API).â Daniel
May 1 at 15:33
Unused variables are typically named
_. Prefixing a name with an underscore is usually done to distinguish 'private' names from 'public' names (those listed in __all__, or at least those part of the API).â Daniel
May 1 at 15:33
@Coal_ I remember seeing unused
_ arguments suggested as a PEP proposal. Was that proposal ever approved?â Steven Vascellaro
May 1 at 15:37
@Coal_ I remember seeing unused
_ arguments suggested as a PEP proposal. Was that proposal ever approved?â Steven Vascellaro
May 1 at 15:37
As a PEP on its own? I'm looking through the list of PEPs now, but can't find it.
â Daniel
May 1 at 15:56
As a PEP on its own? I'm looking through the list of PEPs now, but can't find it.
â Daniel
May 1 at 15:56
1
1
I may have been mistaken about PEP. IâÂÂve found there isnâÂÂt much consensus on how to name unused arguments, but Pylint favors descriptive names prefixed with underscore.
â Steven Vascellaro
May 1 at 16:00
I may have been mistaken about PEP. IâÂÂve found there isnâÂÂt much consensus on how to name unused arguments, but Pylint favors descriptive names prefixed with underscore.
â Steven Vascellaro
May 1 at 16:00
add a comment |Â
up vote
0
down vote
Is this the proper(, pythonic) way to bind a keyboard key and GUI button?
Sure. It's hard to judge exactly what you mean by 'proper', but it works, and I don't see any major caveats with this approach. Binding the callback to the button and calling button.focus_set() works just as well, but your approach makes more sense. Think about it: Does the callback apply only to the button? At least in the case of the quit-callback, no; no matter what widget has focus, pressing 'q' should quit the application.
Some other remarks:
Using wildcard imports (
from <module> import *) is discouraged for a number of reasons. For one, using wildcard imports can cause conflicts if two symbols with the same name, defined in different namespaces, are imported into the global namespace. Secondly, for other developers, there's no way to quickly tell where an object was defined.PEP-8 proposes sorting
importstatements alphabetically.Unless you have compelling reasons to use Python 2, switch to Python 3! Version 2.7 will only be supported until 2020 (see PEP-373).
add a comment |Â
up vote
0
down vote
Is this the proper(, pythonic) way to bind a keyboard key and GUI button?
Sure. It's hard to judge exactly what you mean by 'proper', but it works, and I don't see any major caveats with this approach. Binding the callback to the button and calling button.focus_set() works just as well, but your approach makes more sense. Think about it: Does the callback apply only to the button? At least in the case of the quit-callback, no; no matter what widget has focus, pressing 'q' should quit the application.
Some other remarks:
Using wildcard imports (
from <module> import *) is discouraged for a number of reasons. For one, using wildcard imports can cause conflicts if two symbols with the same name, defined in different namespaces, are imported into the global namespace. Secondly, for other developers, there's no way to quickly tell where an object was defined.PEP-8 proposes sorting
importstatements alphabetically.Unless you have compelling reasons to use Python 2, switch to Python 3! Version 2.7 will only be supported until 2020 (see PEP-373).
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Is this the proper(, pythonic) way to bind a keyboard key and GUI button?
Sure. It's hard to judge exactly what you mean by 'proper', but it works, and I don't see any major caveats with this approach. Binding the callback to the button and calling button.focus_set() works just as well, but your approach makes more sense. Think about it: Does the callback apply only to the button? At least in the case of the quit-callback, no; no matter what widget has focus, pressing 'q' should quit the application.
Some other remarks:
Using wildcard imports (
from <module> import *) is discouraged for a number of reasons. For one, using wildcard imports can cause conflicts if two symbols with the same name, defined in different namespaces, are imported into the global namespace. Secondly, for other developers, there's no way to quickly tell where an object was defined.PEP-8 proposes sorting
importstatements alphabetically.Unless you have compelling reasons to use Python 2, switch to Python 3! Version 2.7 will only be supported until 2020 (see PEP-373).
Is this the proper(, pythonic) way to bind a keyboard key and GUI button?
Sure. It's hard to judge exactly what you mean by 'proper', but it works, and I don't see any major caveats with this approach. Binding the callback to the button and calling button.focus_set() works just as well, but your approach makes more sense. Think about it: Does the callback apply only to the button? At least in the case of the quit-callback, no; no matter what widget has focus, pressing 'q' should quit the application.
Some other remarks:
Using wildcard imports (
from <module> import *) is discouraged for a number of reasons. For one, using wildcard imports can cause conflicts if two symbols with the same name, defined in different namespaces, are imported into the global namespace. Secondly, for other developers, there's no way to quickly tell where an object was defined.PEP-8 proposes sorting
importstatements alphabetically.Unless you have compelling reasons to use Python 2, switch to Python 3! Version 2.7 will only be supported until 2020 (see PEP-373).
answered Apr 10 at 10:08
Daniel
4,1132836
4,1132836
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191477%2fbinding-a-keyboard-key-to-a-tkinter-button%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
This is the actual code I'm using. I haven't implemented the other functions yet, and I was hoping to just get the code implemented thus-far reviewed. In fact, the original question was just asking about reviewing one specific portion of the code - that is, the binding of the keystrokes in association with the buttons in the GUI. However, that specific-level of question was downvoted and given a recommendation to adhere to the guidance in the help center. I understand there may be a common issue of incomplete code segments posted, but I have truly included the entire module.
â user3.1415927
Apr 7 at 15:03
This question has been brought to attention on meta.
â Simon Forsbergâ¦
Apr 7 at 15:53
On the last edit: There really isn't a GUI-agnostic way to ask this question. Each library will have its own way of handling button binding. An answer in PyQT would be useless for tkinter.
â Steven Vascellaro
May 1 at 15:39
@StevenVascellaro interesting, I am unfamiliar with any other GUI options for python. In fact, I'd be open to suggestions with those other frameworks, if they are also pythonic - hence the leaving of the wording. Although I do understand the wording change suggestion (since my code was already using tkinter), I'd be open to the correction I see from time to time on SE of: 'Yes, it will work this way, but a better way is to XYZ.' I'm here to learn! :)
â user3.1415927
May 1 at 15:42
@user3.1415927 I'm using tkinter myself, but PyQT is a popular alternative. (See Graphic User Interface FAQ)
â Steven Vascellaro
May 1 at 15:45