ValueError: literal inválido para int () com base 10: '' (Tkinter)

Sep 10 2020

Quando tento executar este código, ValueErroraparece um aludindo à função numRandom. Achei que Python pudesse passar uma representação de string de um int para um int.

import tkinter
import random

window = tkinter.Tk()
window.geometry('600x500')

x = random.randint(1,300)
remainingTime = True
Attempts = 4

def numRamdom():
    global Attempts
    while Attempts > 0:
        numWritten = int(entryWriteNumber.get())
        if numWritten > x:
            lblClue.configure(text = 'Its a bigger number')
            Attempts = Attempts -1
        if numWritten < x:
            lblClue.configure(text = 'Its a smaller number')
            Attempts = Attempts -1
        if numWritten == x:
            lblClue.configure(text = 'Congratulations ;)')
            remainingTime = False
            return remainingTime, countdown(0)
        if Attempts == 0:
            remainingTime = False
            return remainingTime, countdown(0), Attempts, gameOver()

entryWriteNumber = tkinter.Entry(window)
entryWriteNumber.grid(column = 0, row = 1, padx = 10, pady = 10)

numRamdom()

window.mainloop()

Respostas

CoolCloud Sep 10 2020 at 21:43

O problema é porque quando o código é executado, ele chama diretamente numRamdom(), ou seja, inicialmente os widgets de entrada estão vazios e eles o executam com esses widgets de entrada vazios e, portanto, o erro. Portanto, basta atribuir um botão e um comando, como:

b = tkinter.Button(root,text='Click me',command=numRamdom)
b.grid(row=1,column=0)

Certifique-se de dizer isso antes e mainloop()depois de def numRamdom():. O botão executa a função apenas quando o botão é clicado.

Ou se você quiser sem botões, tente:

MÉTODO 1:

root.after(5000,numRamdom) #after 5 sec it will execute function

Mas lembre-se, se o usuário não entrar corretamente em 5 segundos, algum erro aparecerá.

MÉTODO-2:

def numRamdom(event):
......

entryWriteNumber.bind('<Return>',numRamdom)

Isso é para que, se você pressionar a tecla enter no widget de entrada (após inserir os dados), ele executará a função.

Espero que isso ajude, deixe-me saber se houver algum erro.

Felicidades

SanguineL Sep 10 2020 at 21:53

Aqui está um exemplo totalmente funcional baseado em seu código. Seu problema era tentar converter o conteúdo da Entrada antes que qualquer coisa estivesse dentro dela. Para corrigir esse problema, você pode adicionar um botão que chama o comandonumRamdom()

import tkinter
import random

window = tkinter.Tk()
window.geometry('600x500')

x = random.randint(1,300)
remainingTime = True
Attempts = 4

def numRamdom():
    global Attempts, lblClue, x
    if Attempts > 0:
            numWritten = int(entryWriteNumber.get())
            if numWritten < x:
                lblClue.configure(text = 'Its a bigger number')
                Attempts = Attempts -1
            elif numWritten > x:
                lblClue.configure(text = 'Its a smaller number')
                Attempts = Attempts -1
            else:
                lblClue.configure(text = 'Congratulations ;)')
                remainingTime = False
                #return remainingTime, countdown(0)
            if Attempts == 0:
                remainingTime = False
                #return remainingTime, countdown(0), Attempts, gameOver()
    else:
        lblClue.configure(text = "You ran out of attempts!")

entryWriteNumber = tkinter.Entry(window)
entryWriteNumber.grid(column = 0, row = 1, padx = 10, pady = 10)

entryWriteButton = tkinter.Button(window, text = "Push me!", command = numRamdom)
entryWriteButton.grid(column = 1, row = 1)

lblClue = tkinter.Label(window)
lblClue.grid(row = 2, column = 1)


window.mainloop()

Você ainda obterá um erro se o valor passado não puder ser convertido em um inteiro, mas isso é fácil de corrigir com uma ifinstrução.