Dustin
Dustin

Reputation: 733

Triggering a button click with the enter key in Python

Please forgive me in advance, as I am very new to Python. I'm putting together this code for a very simple rate calculator and want to make it where when the Enter key is pressed the program calculates the total (executes the calculate command). Python returns an error saying that Calculate is not defined, however I've defined it several lines above. Any ideas?

import tkinter
from tkinter import ttk
from tkinter import *

    root = Tk()
    root.withdraw()

class Adder(ttk.Frame):

"""The adders gui and functions."""
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)
        self.root = parent
        self.init_gui()


    def on_quit(self):
        """Exits program."""
        quit()

    def calculate(self, *args):
        """Calculates the sum of the two inputted numbers."""
        num1 = int(self.num1_entry.get())
        num2 = float(self.num2_entry.get())
        num3 = ((num1/2000) * num2)
        self.answer_label['text'] = num3





    def init_gui(self):
        self.root.title('Rate Calculator')
        self.root.option_add('*tearOff', 'FALSE')

        self.grid(column=0, row=0, sticky='nsew')

        self.menubar = tkinter.Menu(self.root)

        self.menu_file = tkinter.Menu(self.menubar)
        self.menu_file.add_command(label='Exit', command=self.on_quit)

        self.menu_edit = tkinter.Menu(self.menubar)

        self.menubar.add_cascade(menu=self.menu_file, label='File')
        self.menubar.add_cascade(menu=self.menu_edit, label='Edit')

        self.root.config(menu=self.menubar)

        self.num1_entry = ttk.Entry(self, width=5)
        self.num1_entry.grid(column=1, row = 2)

        self.num2_entry = ttk.Entry(self, width=5)
        self.num2_entry.grid(column=3, row=2)

        self.calc_button = ttk.Button(self, text='Calculate',
                command=self.calculate)
        self.calc_button.grid(column=0, row=3, columnspan=4)

        self.answer_frame = ttk.LabelFrame(self, text='Answer',
                height=100)
        self.answer_frame.grid(column=0, row=4, columnspan=4, sticky='nesw')

        self.answer_label = ttk.Label(self.answer_frame, text='')
        self.answer_label.grid(column=0, row=0)

        # Labels that remain constant throughout execution.
    ttk.Label(self, text='Rate Calculator').grid(column=0, row=0,
            columnspan=4)
    ttk.Label(self, text='Weight').grid(column=0, row=2,
            sticky='w')
    ttk.Label(self, text='Rate').grid(column=2, row=2,
            sticky='w')

    ttk.Separator(self, orient='horizontal').grid(column=0,
            row=1, columnspan=4, sticky='ew')

    for child in self.winfo_children():
        child.grid_configure(padx=5, pady=5)


root.bind('<Return>', calculate)


if __name__ == '__main__':
    root = tkinter.Tk()
    Adder(root)
    root.mainloop()

Upvotes: 1

Views: 4345

Answers (2)

PM 2Ring
PM 2Ring

Reputation: 55469

I've reorganised your code slightly so it now calls the calculate method either when you press the button or when you hit Enter.

import tkinter as tk
from tkinter import ttk

class Adder(ttk.Frame):
    """The adders gui and functions."""
    def __init__(self, parent, *args, **kwargs):
        ttk.Frame.__init__(self, parent, *args, **kwargs)
        self.root = parent
        self.init_gui()

    def on_quit(self):
        """Exits program."""
        tk.quit()

    def calculate(self, *args):
        """Calculates the sum of the two inputted numbers."""
        num1 = int(self.num1_entry.get())
        num2 = float(self.num2_entry.get())
        num3 = ((num1/2000) * num2)
        self.answer_label['text'] = num3

    def init_gui(self):
        self.root.title('Breakbulk Rate Calculator')
        self.root.option_add('*tearOff', 'FALSE')

        self.grid(column=0, row=0, sticky='nsew')

        self.menubar = tk.Menu(self.root)

        self.menu_file = tk.Menu(self.menubar)
        self.menu_file.add_command(label='Exit', command=self.on_quit)

        self.menu_edit = tk.Menu(self.menubar)

        self.menubar.add_cascade(menu=self.menu_file, label='File')
        self.menubar.add_cascade(menu=self.menu_edit, label='Edit')

        self.root.config(menu=self.menubar)

        self.num1_entry = ttk.Entry(self, width=5)
        self.num1_entry.grid(column=1, row = 2)

        self.num2_entry = ttk.Entry(self, width=5)
        self.num2_entry.grid(column=3, row=2)

        self.calc_button = ttk.Button(self, text='Calculate',
                command=self.calculate)
        self.calc_button.grid(column=0, row=3, columnspan=4)

        self.answer_frame = ttk.LabelFrame(self, text='Answer',
                height=100)
        self.answer_frame.grid(column=0, row=4, columnspan=4, sticky='nesw')

        self.answer_label = ttk.Label(self.answer_frame, text='')
        self.answer_label.grid(column=0, row=0)

        # Labels that remain constant throughout execution.
        ttk.Label(self, text='Breakbulk Rate Calculator').grid(column=0, row=0,
                columnspan=4)
        ttk.Label(self, text='Weight').grid(column=0, row=2,
                sticky='w')
        ttk.Label(self, text='Rate').grid(column=2, row=2,
                sticky='w')

        ttk.Separator(self, orient='horizontal').grid(column=0,
                row=1, columnspan=4, sticky='ew')

        for child in self.winfo_children():
            child.grid_configure(padx=5, pady=5)

        self.root.bind('<Return>', lambda event: self.calculate())


if __name__ == '__main__':
    root = tk.Tk()
    Adder(root)
    root.mainloop()

To create a callback with the proper signature for .bind I've used a lambda function that simply discards the Event object that gets passed to it.

I also got rid of the evil from tkinter import * wildcard import.

Upvotes: 1

LAS
LAS

Reputation: 179

The problem is coming from this part of your code

root.bind('<Return>', calculate)

change it to

root.bind('<Return>', self.calculate)

it will work.

Upvotes: 0

Related Questions