Fraans
Fraans

Reputation: 117

Python Tkinter: How to combine keyboard prompts and clickable buttons adequately?

Hello Stack community,

As I tried writing a simple google searchbar GUI app, I seem to have created a trade-off between either a clickable GUI button or a working keyboard command. This depends on passing 'self' into the function called 'google'. Without 'self' the GUI Submit button will work, and the Enter key will raise an error in the console. With 'self' passed into google, the Enter key will work, but the GUI Submit button raises the opposite error. It has to do with the amount of arguments passed into this function 'google'.

Is there a way to make both the submit button and the Enter key work?

In this example the GUI Submit button works, the Enter key will give an error:

#!/usr/bin/env python3
from tkinter import ttk
from tkinter import *
import webbrowser

def google(): 
    url = "https://www.google.nl/#q=" + search.get()
    webbrowser.open_new_tab(url)

#GUI
root = Tk()
search = StringVar()
ttk.Entry(root, textvariable=search).grid()
submit = ttk.Button(root, text="Search", command=google).grid()
root.bind("<Return>", google)
root.mainloop()

Upvotes: 0

Views: 503

Answers (2)

user4171906
user4171906

Reputation:

Add a default for the times that nothing is passed to the function. It doesn't matter what it is since you don't use it.

def google(event=None): 
    print("google function called")
##    url = "https://www.google.nl/#q=" + search.get()
##    webbrowser.open_new_tab(url)

#GUI
root = Tk()
search = StringVar()
ttk.Entry(root, textvariable=search).grid()
submit = ttk.Button(root, text="Search", command=google).grid()
root.bind("<Return>", google)
root.mainloop()

Upvotes: 2

Paul Rooney
Paul Rooney

Reputation: 21609

The reason it fails is that a Tkinter callback function passes an event argument. So any callback you pass has to have this argument. Adding an argument fixes it for the bind but then breaks it for the submit.

This is because for the submit no argument is passed and your function now requires an argument. So basically what it means is you can't use the same function for both purposes.

One simple way to get round this is to use a lambda in the bind call.

root.bind("<Return>", lambda e: google())

Upvotes: 2

Related Questions