0

I want to make a button that when clicked opens a new window (tk.toplevel), is there a way to make the button only work once, (it only makes one new window when clicked thereafter the the button when clicked does not do anything)

from the below code I can make unlimited amount of top levels by clicking the button BUT I just want it to create one on click.

import tkinter as tk

class run:      # pls ignore if there are any syntrax error/spelling because I typed this in stack overflow
    def __init___(self, master)
        button = tk.button(master, text="btn", self.command=make_new)
        button.grid()
    def make_new()
        new = tk.toplevel(master)

master1 = tk.Tk()
i = Run(master1)
master1.mainloop()

*** I didn't put the original code because it has too many classes/functions to put here

*** this is the other question which I made which has more of the code: How to make a tkinter button open only one Toplevel?

coder_not_found
  • 202
  • 2
  • 13
  • 1
    _"from the below code I can make unlimited amount of top levels by clicking the button"_ - that is definitely not true. Have you even tried to run the code you posted? It doesn't look like you've even attempted to solve the problem by yourself. – Bryan Oakley Mar 04 '21 at 14:15
  • if the command for clicking the button is make_new(); then if the make_new() function makes a New top level, Then i would definitely be able to make a lot of top levels by clicking the button again and again. – coder_not_found Mar 04 '21 at 14:21
  • @Bryan also I tried using a counter in the original code, and wasn't successful; and the original code has way too many functions/classes/files to put here, so I simplified the code here, so I don't think there's anything wrong with the question :) – coder_not_found Mar 04 '21 at 14:24
  • _"if the command for clicking the button is make_new();"_ - then `make_new()` will be called _immediately_, and clicking the button will do nothing. We don't need the original code, we need a [mcve]. – Bryan Oakley Mar 04 '21 at 14:44
  • I made the original a bit smaller and put it in this question: [https://stackoverflow.com/questions/66472553/how-to-make-a-tkinter-button-open-only-one-toplevel] but I didn't get any answers that worked so I made it even simpler and put it here, thanks – coder_not_found Mar 04 '21 at 14:53

2 Answers2

2

I made some changes to your code so that when you click the button, it will create a toplevel, and if you click multiple times, it will not create more of them:

import tkinter as tk


class Run:
    def __init__(self, master):
        self.master = master
        self.toplevels = 0
        button = tk.Button(master, text="btn", command=self.make_new)
        button.pack()

    def make_new(self):
        if not self.toplevels:
            new = tk.Toplevel(self.master)
            self.toplevels += 1

master1 = tk.Tk()
i = Run(master1)
master1.mainloop()
MercifulSory
  • 337
  • 1
  • 14
  • This is good, though if you delete the top-level there will be no way to create another one. It's not clear if that's what the OP needs. – Bryan Oakley Mar 04 '21 at 14:45
1

The trouble here: The "loop" iteration it's too fast for human response and a action can be still active to multiple iterations.

Posible solution/Tip #1

¿It's possible to add a wait(miliSeconds) (Or similar function) after de new = tk.toplevel(master)? I faced the same issue on Arduino, but it's because the "loop" it's too fast for human response, so you may need to add a little "wait" after open the new window (Maybe half of a second or 1 second), so you will have only 1 new window.

Posible solution/Tip #2

If you can't add a wait(miliSeconds) function, you can try adding a flag to the main method, when you enter the make_new() method ask flag == 0 if it is, turn it into 1 and proceed, if the flag isn't 0, simply skip opening a new window

Kevin
  • 93
  • 6
  • 1
    Your first statement doesn't seem to make much sense. There is no loop other than `mainloop`, and it doesn't run fast. It is idle most of the time, waiting for events. Waiting won't solve the problem of being able to open only one window. – Bryan Oakley Mar 04 '21 at 14:52
  • I think using flag method works but I don't understand why the loop will be too fast, and I don't think using a "wait" function would stop it from making multiple top levels on button click. solution #2 works :) – coder_not_found Mar 04 '21 at 15:04
  • 1
    Good to read that solution 2 works. **¿Why a loop is so fast?** Easy ¿How many instructions a computer handles in a second? Hundreds, and with the current power of processors and multithreading, the number can grow to thousands of instructions per second (Operative system class teach me that). That's that can I tell you. – Kevin Mar 04 '21 at 15:08