Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

303
Visualizações
How do I prevent focus change if an entry is invalid?

I want if one field has invalid entry, message to be displayed on moving out of that field and focus should remain on that field. But in following code validation of next field is also triggered when moving out of first field. I have commented set focus, otherwise, it gets into an infinite loop.

from tkinter import *
from tkinter import ttk, messagebox

root = Tk()

def callback1():
    if (len(e1.get()) <4):
        messagebox.showinfo("error", "Field 1 length < 4")
        #e1.focus_set()
        return False
    else:
        return True
    
def callback2():
    if (len(e2.get()) <4):
        messagebox.showinfo("error", "Field 2 length < 4")
        #e2.focus_set()
        return False
    else:
        return True

e1 = Entry(root, validate="focusout", validatecommand=callback1)
e1.grid()
e2 = Entry(root,  validate="focusout", validatecommand=callback2)
e2.grid()
root.mainloop()
over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

When you place your cursor in e1, type something which does not satisfy the validatecommand condition and then try to place your cursor in e2, the following sequence of events takes place:

  1. e1 loses focus and calls callback1
  2. Meanwhile, the cursor is placed in e2 and e2 gets focus
  3. The msgbox window for e1 takes focus and is ready to pop up just when...
  4. e2 loses focus and calls callback2
  5. The msgbox window for e2 pops up
  6. This is followed by the pop up for e1 which was waiting in the queue

The root cause for the problem is that the messagebox window takes focus, which in turn triggers the other entry box. This approach seems to be highly fragile due to the strong interplay of events.

Notice that if you just print the information to the terminal, everything works perfectly as the terminal doesn't take focus.

So, I would recommend you display the information using an alternate method where the widget showing the information won't steal focus. One option is to display the information using a label.


Now coming to your second problem, if you want the entry to retain focus if the entered text is not valid, you could use a global variable (hanging) to keep track of whether the user is in the process of filling an entry successfully.

If the user is in the process of filling an entry, he/she will not be able to place the cursor in the other entry because FocusIn1 and FocusIn2 return "break" when hanging equals True.

You can replace the print statements in the below working code using a label.


Working Code:

from tkinter import *
from tkinter import ttk, messagebox

root = Tk()
hanging = False #True implies that the user is in the process of filling an entry successfully

def onFocusOut1():
   global hanging
   hanging = True
   if (len(e1.get()) <4):
       print("error", "Field 1 length < 4")
       e1.focus_set()
       return False
   else:
      hanging = False
      return True
    
def onFocusOut2():
   global hanging
   hanging = True
   if (len(e2.get()) <4):
       print("error", "Field 2 length < 4")
       e2.focus_set()
       return False
   else:
       hanging = False
       return True

def onFocusIn1():
    if hanging:
       return "break"
    e1.configure(validate="focusout", validatecommand=onFocusOut1)

def onFocusIn2():
    if hanging:
       return "break"
    e2.configure(validate="focusout", validatecommand=onFocusOut2)

e1 = Entry(root)
e1.grid()
e2 = Entry(root)
e2.grid()

#Binding both the entries to FocusIn
e1.bind("<FocusIn>", lambda e: onFocusIn1())
e2.bind("<FocusIn>", lambda e: onFocusIn2())

root.mainloop()

PS: It turns out that you can actually use messagebox.showinfo itself in place of print in the working code. The first problem got solved automatically along with the second one. So, this gives the complete solution to your problem.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda