masaya
masaya

Reputation: 87

How to enter number in Entry using button in tkinter

I want to add numbers (only 4 numbers) to entry via button in tkinter. I tried this code but it's not working. I need some suggestions.

import tkinter as tk
win = tk.Tk()

var = tk.StringVar()
var_entry = tk.Entry(win,text='var',textvariable=var)

def handle_button(event):
    return var.insert(0,4)

def window():
    global win
    var_entry.grid(row =1 ,column =2)

    button1 = tk.Button(win,text = '1' ,textvariable = 1)
    button1.bind("<Button-1>", handle_button)
    button1.grid(row = 2 , column = 0)
    # similarly I defined all the buttons.


windows()
win.mainloop()

The error it shows is:

AttributeError: 'StringVar' object has no attribute 'insert'

Upvotes: 0

Views: 11101

Answers (3)

osaid
osaid

Reputation: 1

""" Below code restricts the ttk.Entry widget to receive type 'str'. """

import tkinter as tk
from tkinter import ttk


def is_type_int(*args):
  item = var.get()
  try:
    item_type = type(int(item))
    if item_type == type(int(1)):
      print(item)
      print(item_type)
  except:
    ent.delete(0, tk.END)


root = tk.Tk()
root.geometry("300x300")

var = tk.StringVar()

ent = ttk.Entry(root, textvariable=var)
ent.pack(pady=20)

var.trace("w", is_type_int)

root.mainloop()

Upvotes: 0

masaya
masaya

Reputation: 87

I tried this one and it also worked.

import tkinter as tk
win = tk.Tk()

var = tk.StringVar()
var_entry = tk.Entry(win,text='var',textvariable=var)
var_entry.grid()

def handle_button(event):
    button_arg = event.widget['text']
    var_entry.insert(0,'end')

button1 = tk.Button(win,text = '1')
button1.bind("<Button-1>", handle_button)
button1.grid()
# similarly I defined all the buttons.


windows()
win.mainloop()

Upvotes: 1

Mike - SMT
Mike - SMT

Reputation: 15236

To get the behavior you are looking for all you need to do is:

Change this:

def handle_button(event):
    return var.insert(0,4)

To this:

def handle_button(event):
    var.set(4)

That said there are a few things wrong with your code that are not useful here.

  1. Looking at return var.insert(0, 4). This return is actually not doing anything useful here because what it is trying to do is return the results of calling var.insert(0, 4) and assigning it to what ever called that function. 2 major problems with this. var.insert(0, 4) is not going to return a useful value for the return command to help and 2nd you cannot return a result to the binding it has no use. Instead delete the return all together and just write the command used to update the StringVar. In this case var.set(4).

  2. Looking at var_entry = tk.Entry(win,text='var',textvariable=var). The text = 'var' is 100% useless here. In an entry field the argument text is actually short for textvariable so what is going on here is you are assigning the string var to the text variable and then immediately reassigning the textvariable to the StringVar(). So lets rewrite that line to just var_entry = tk.Entry(win, textvariable=var).

  3. Looking at button1 = tk.Button(win,text = '1' ,textvariable = 1) you are doing something here that does nothing to help. textvariable = 1 has no purpose here. So lets just delete that. Rewrite that line as button1 = tk.Button(win, text='1')

  4. Looking at button1.bind("<Button-1>", handle_button) is overkill for something the button can handle with the command argument. Delete this line entirely and rewrite the button1 to contain the command. Like this: button1 = tk.Button(win, text='1', command=handle_button)

  5. Looking at def window(): we can remove this function and take its content and move it to the global name space. Right now there is no benefit to using a function to set up the GUI so instead lets remove the extra step.

With all that you should have something that looks like this:

import tkinter as tk


win = tk.Tk()
var = tk.StringVar()

var_entry = tk.Entry(win, textvariable=var)
var_entry.grid(row=1, column=2)

def handle_button():
    var.set(4)

tk.Button(win, text='1', command=handle_button).grid(row=2, column=0)

win.mainloop()

I am not sure if you have heard of lambda just yet but it can be used here to reduce our code just a little bit more. lambda is used to create anonymous function and what that means is we can create one line functions that do not require us to define a function by name.

So if we delete the def handle_button(): function and then we change the button1 command to a lambda we can save our selves 2 more lines of code that is not really helping us or improving readability.

The new final code should look like this:

import tkinter as tk


win = tk.Tk()
var = tk.StringVar()

var_entry = tk.Entry(win, textvariable=var)
var_entry.grid(row=1, column=2)

tk.Button(win, text='1', command=lambda: var.set(4)).grid(row=2, column=0)

win.mainloop()

In making all these changes we cut your code in half to achieve the same results and it is a bit cleaner to read.

Upvotes: 0

Related Questions