0

I need to do some basic conditional logic on entries, but I am running into an issue.

There are 2 entries, "dosage" and "week". In both will be entered only numbers (25, 3, etc.). I have a "Get Info" button that activates a function what will preform conditional logic on the entries, although since when the program runs there isn't any text inside of the entries, I run into an error.

ValueError: invalid literal for int() with base 10: ''

Here is my code:

from tkinter import *
import tkinter.font as font

# Window setup
root = Tk()
root.title("Dosage GUI")
root.geometry("330x450")

# Entries
weekEntry = Entry(root)
dosageEntry = Entry(root)

# Labels to describe entries
weekLabel = Label(root, text="Week #")
dosageLabel = Label(root, text="Dosage in mg (enter only a number)")

# Information text
# State = disabled, but when changing text, change to normal, then back to disabled
def setInfoText(textBox, text):
    textBox.config(state="normal")
    textBox.insert(1.0, text)
    textBox.config(state="disabled")

infoTextFont = font.Font(size=8)
infoText = Text(root, height=17, width=30, padx=10,pady=10, state="disabled", font=infoTextFont, bd=5,bg="#e8ebea")

# Get Info button
def getInfo(week, dosage):
    # Check what is possible based on the dosage rules
    if week > 3:
        setInfoText(infoText, "PI may change dosage if needed.")
    if week < 3:
        setInfoText(infoText, "PI cannot change dosage until week 3.")

getInfoFont = font.Font(size=13,weight="bold")
getInfoBut = Button(root, text="Get Info", padx=20,pady=20,bd=10,bg="#7299ed",activebackground="#729ffc", fg="#40e677", command=getInfo(int(weekEntry.get()), int(dosageEntry.get())))
getInfoBut['font'] = getInfoFont

# Grid
weekEntry.grid(row=0,column=5)
dosageEntry.grid(row=0, column=10)

weekLabel.grid(row=5,column=5)
dosageLabel.grid(row=5,column=10)

getInfoBut.place(x=100,y=70)

infoText.place(x=50,y=170)

# mainloop
root.mainloop()

Databas3
  • 21
  • 4

1 Answers1

0

The command keyword argument needs a function as parameter.

Right now you're passing getInfo(int(weekEntry.get()), int(dosageEntry.get())) - which is the return value of getInfo - which is None (because there are no return statements in that function).

Instead, you may want to pass this a statement inside a lambda - this way you create a function that gets called whenever that button is pressed:

getInfoBut = Button(root, text="Get Info", padx=20,pady=20,bd=10,bg="#7299ed",activebackground="#729ffc", fg="#40e677", command=lambda: getInfo(int(weekEntry.get()), int(dosageEntry.get())))

The reason the error occurs is because Python attempts to evaluate the call to getInfo even before the UI shows - the fields weekEntry anddosageEntry are empty at this point - attempting to convert an empty string to an int results in the error.

Omer Tuchfeld
  • 2,886
  • 1
  • 17
  • 24
  • While what you say is true as far as it goes, in this case I would suggest that the OP define the callback function normally with a `def` instead of using `lambda` because the handling of the two possibly empty `Entry` values will like make the latter form too complicated. – martineau Aug 04 '20 at 15:18
  • Or alternatively make sure they have default values / cannot be set to empty by the user in first place. Or don't have the button pass any values to the function - have the function access the values on its own – Omer Tuchfeld Aug 04 '20 at 15:22
  • This worked! Thank you so much!! Although why do we have to make it lambda? Doesn't the command=getInfo() already have the logic of only calling it when it's pressed? – Databas3 Aug 04 '20 at 15:52
  • When you write `command=getInfo(...)` the expression `getInfo(...)` gets evaluated when the script loads, even before the GUI is shown. That's just how Python works. You try to instantiate a Button object - to do that you need to pass it parameters - in order to pass it the `command` parameter - the value of that parameter needs to be evaluated, and that evaluation happens at the start. If you turn that expression into a lambda instead of a function call - the evaluation of a lambda doesn't actually run the code inside the lambda - that only happens when the lambda gets called by `getInfoBut` – Omer Tuchfeld Aug 04 '20 at 15:57
  • ah, @Omer i think i see. so the command=getInfo() is already defined and processed before i even interact with the button.. good to knwo! thanks for the help! – Databas3 Aug 15 '20 at 00:42