0

I am trying to display a new label after a couple of seconds and destroy the old one but it doesn`t work as wished, when I press the button nothing happens. How do I do it?

What I have tried:

 if f"{user}::{pword}" in accounts:
        ID["text"] = "Checking..."
        ID.after(500)
        ID.destroy()
        ID.after(500)
        ID["text"] = "Login succesful!"

        return True
    else:
        print("Failed")
        return False
antique
  • 39
  • 7
  • 1
    Use `ID.after(500, ID.destroy)` instead of `ID.after(500); ID.destroy(); ID.after(500)`. Look at [this](https://stackoverflow.com/questions/25753632/tkinter-how-to-use-after-method) to learn how to properly use `.after` scripts. – TheLizzard May 24 '21 at 19:23
  • It is working but when I try to add another text after that `ID2["text"] = "Succesful login!"` it`s showing just the second text and it is ignoring the first text. – antique May 24 '21 at 19:27
  • I assume your label is named ID. If this is the case then you are destroying the label and you cannot then add text to something that does not exist. Simply update the label instead. ID.configure(text='new text'). You will need to use a lambda combined with the after statement. – Mike - SMT May 24 '21 at 19:29
  • You can't have linear delays in `tkinter` programs. Where you have: `ID["text"] = ... `, that does not immediately update the GUI. Your program has to return to the `tkinter` main loop before anything can be changed on screen. – quamrana May 24 '21 at 19:30

1 Answers1

1

You have 2 problems here.

1st your ID.after(500) in essence functions exactly like sleep() when you do not pass an argument. Because of tkinters mainloop you end up freezing the program until the time has passed.

2nd you are destroying the object (label) you are trying to update. Instead of destroying and recreating you can simply update. In this case because you need to pass the new value to update the label you need to use a lambda statement so the program does not try to execute the call to configure instantly instead of waiting.

Example:

import tkinter as tk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.ID = tk.Label(self, text='starting text')
        self.ID.pack()
        self.after(2000, lambda: self.ID.configure(text='new text'))
        print('test')


if __name__ == "__main__":
    App().mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • It works but how do I move the second label in another position because it stays in the same place where the first was? Place isn`t working. – antique May 24 '21 at 19:42
  • 2
    @antique I suggest that you look at some tkinter tutorials. Look at *how to use .after in tkitner* – TheLizzard May 24 '21 at 19:44
  • @TheLizzard I didn`t find anything on how to reposition a label after configuring it. Thats why I asked. – antique May 24 '21 at 19:54
  • @antique you should avoid place() it has its uses but should not be used for basic interface design stuff. Use prack and grid. Personally I use grid() for just about everything. It works for my needs and once you figure it out it makes way more since than place(). – Mike - SMT May 24 '21 at 19:55
  • 2
    @antique You need to learn how to use `.after` properly and then how to change the label's position/text. After that it will be trivial to do what you were asking for. I am not going to give you the code unless I know that you have at least looked at a few tutorials – TheLizzard May 24 '21 at 19:58
  • @antique that said your question was about an issue with after/destroy not working the way you were wanting. For a question about geometry placement you should ask a new question. However you can use `grid()` again on the same label to change its position. but if it is the only thing in your window it probably wont move due to automatic resizing of the containers. There are countless example here on SO and youtube dealing with the geometry manager. I even have several post on the matter. – Mike - SMT May 24 '21 at 19:58