1

I am learning to do a GUI using tkinter and I create an integer entry which is working fine except that whenever I run my program the number 0 is already put in the entry, is there anyway to remove it and just have nothing instead? It doesn't do that with strings

I checked answers like this one: https://stackoverflow.com/a/39879154/13061992 but I didn't work (the user already has said that is only for strings but I gave it a shot anyway)

To explain more, I am creating a text box using the following:

tries_var = tk.IntVar()
tries_label = tk.Label(root, text='Number Of Tries', font=('calibre', 10, 'bold'))
tries_entry = tk.Entry(root, textvariable=tries_var, font=('calibre', 10, 'normal'))
tries_label.grid(row=2, column=0)
tries_entry.grid(row=2, column=1)

When I run the program I have 0 written by default, like this: enter image description here

I want to get rid of this and instead have the box to be empty, any help would be appreciated.

Sergio
  • 275
  • 1
  • 15
  • 1
    I am not exactly sure what you are trying to do. Are you trying to create an entry where the user can only put numbers? – TheLizzard Feb 28 '21 at 19:13

2 Answers2

4

The reason for this is, you are using tk.IntVar() which by default will put a 0 onto the Entry widget. To get rid of this, change tk.IntVar() to tk.StringVar().

tries_var = tk.StringVar()

Though keep in mind, tk.IntVar.get() will return int, now that you are using tk.StringVar, you might need int(tk.StringVar.get()), given that your input is completely numbers.

print(int(tries_var.get()) # Given that, your input is entirely numbers
Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46
  • Is there any better way I don't rather not get into casting and such – Sergio Feb 28 '21 at 19:20
  • @Sergio You mean better or easier? Casting is the easiest, better would be validation, requires more coding. If you ask me, there is no need for using any of this variable, just use `tries_entry.get()` and casting is the simple and better method. – Delrius Euphoria Feb 28 '21 at 19:22
  • I tried doing casting and there are two things that occured: 1. ValueError: invalid literal for int() with base 10: '' and the second one (I am not sure if that is due to the casting or not) I actually have 10 text entries, when I type a number in one of them all of them are getting this number, for example I type 5 in entry1 I get 5 in entries 2 to 10 as well – Sergio Feb 28 '21 at 19:35
  • @Sergio This is because all the textboxes share the same `StringVar()`. And as I said for casting to work, your input should be an integer ONLY – Delrius Euphoria Feb 28 '21 at 19:37
  • Oh thank you, I just noticed (second point fixed). They are integer only, I wrote the number "2" – Sergio Feb 28 '21 at 19:41
  • @Sergio Did you write "2" with the quotes or without? – Delrius Euphoria Feb 28 '21 at 19:42
  • 2
    without quotes but I think I found out the issue, I have 10 entries but some of them are sometimes left empty, so for example when I write in the first entry I get this error on the second, when I write in first two, I get on the third, since I am casting the entry and getting it when it is empty (I don't know how to prevent the program from trying to get the entry if it is empty) I am getting this error as I am casting something empty to into< I will see how to fix it. Thanks a lot. – Sergio Feb 28 '21 at 19:44
  • @Sergio I recommend you read [this](https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/entry-validation.html) too. – Delrius Euphoria Feb 28 '21 at 19:46
  • 2
    thanks big time for all the help! will surely do now. – Sergio Feb 28 '21 at 19:47
2

Try this:

import tkinter as tk

def only_allow_numbers(event):
    char = event.char.lower()
    if (event.state & 4) >> 2:
        # If ctrl is also pressed:
        # Check and handle Ctrl+c, Ctrl+v, Ctrl+x
        # For now I will just allow it
        return None
    if char.isprintable() and (not event.char.isdigit()):
        return "break"

root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
entry.bind("<Key>", only_allow_numbers)

root.mainloop()

It uses bindings. When you return "break" from a binding that key is ignored (isn't inserted in the entry.)

TheLizzard
  • 7,248
  • 2
  • 11
  • 31
  • Validation is much easier to use and understand. – Delrius Euphoria Feb 28 '21 at 19:23
  • 1
    Tkinter has input validation functions built-in which are better than doing a one-off binding. For example, your code won't work if the user uses the mouse to paste a value. See https://stackoverflow.com/questions/4140437/interactively-validating-entry-widget-content-in-tkinter/4140988#4140988 – Bryan Oakley Feb 28 '21 at 20:25
  • I have seen posts using `vadidatecommand` but I have never used it. My guess is that it is the same as me manually binding to each event and returning `"break"` whenever I dislike the user input. – TheLizzard Feb 28 '21 at 20:45