1

My problem is simple, but i really don't know what the issue is. I'm trying to open more than one window almost at the same time, but if i do it like that:

from tkinter import *
import threading
import time

class new_window:
    def build(self, killtime):
        self.w = Tk()
        self.w.update()
        time.sleep(killtime)
        self.w.destroy()
    def __init__(self, killtime):
        threading.Thread(target=self.build(killtime)).start()

a = new_window(2)
time.sleep(2)
b = new_window(2)

it doesn't behave like: "open, wait, open" but instead like: "open, wait until killed, wait, open"

What i mean is that the delay starts after the first window is closed, not after the window started. I thought a Thread would help me out, but it didn't.

Hopefully one of you knows how to fix that.

Toaster
  • 65
  • 6
  • 2
    First you have to understand [Event-driven_programming](https://en.m.wikipedia.org/wiki/Event-driven_programming). Read through [`[tkinter] event driven programming`](https://stackoverflow.com/search?q=is%3Aanswer+%5Btkinter%5D+event+driven+programming+entry), [Tkinter understanding mainloop](https://stackoverflow.com/a/29158947/7414759) and [When to use the Toplevel Widget](http://effbot.org/tkinterbook/toplevel.htm) – stovfl May 08 '20 at 20:34
  • 1
    There's nothing to fix here - a `mainloop` is taking up the whole processing until it's exited as expected. Perhaps you meant to use a `Toplevel` widget? @stovfl provided some great links you should take a look at to better reevaluate your approach. – r.ook May 08 '20 at 20:48
  • @r.ook But there is no mainloop in my example, and also the window creation runs in a seperate thread. I tried it with toplevel instead of Tk, but its just the same issue, also if i delete the .update(). – Toaster May 08 '20 at 21:00
  • If you don't have a mainloop, then the number of functioning Tk windows you can open at the same time is *zero*. – jasonharper May 08 '20 at 22:09
  • @jasonharper Actually, it depends on what editor you use. For example, in IDLE, you don't have to put `.mainloop()`. It works both ways, but I just wanted to point it out. – 10 Rep May 09 '20 at 00:34
  • @jasonharper you are wrong... if you do .update() again and again you dont have to have a mainloop(). – Toaster May 09 '20 at 00:37
  • @Toaster You can still **have** a mainloop, it just isn't required when you have update or after. – 10 Rep May 09 '20 at 00:58
  • If you don't do a `mainloop` you there's no point to use `tkinter` really. The whole point is for the process to handle your UI, but if you just constantly update separate instances of `Tk` it's quite moot. – r.ook May 09 '20 at 01:17
  • 1
    @r.ook I feel mainloop isn't the main aspect of Tkinter. I use tkinter because if it's simplicity. – 10 Rep May 09 '20 at 01:41

2 Answers2

2

You don't really need to use the threading module.

You can use the .after() method to open a new window a little after.

Here is your code:

from tkinter import *
window = Tk()
window.title("window1")
def open_new_window():
    window2 = Toplevel()
    window2.title("Window2")
window.after(1000, open_new_window)
window.mainloop()

Hope this helps!

Edit: The code above opens one window, then stops doing anything. If you want new windows to keep opening with a small delay in between, you can use the below code:

from tkinter import *
window = Tk()
window.title("window1")
def open_new_window():
    window2 = Toplevel()
    window2.title("Window2")

    window.after(1000, open_new_window)
open_new_window()

window.mainloop()

Hope this helps!

10 Rep
  • 2,217
  • 7
  • 19
  • 33
0

I did it like this now. But i still marked the Answer of @TheMaker as the Solution, cause its more compact and easier to understand.

from tkinter import *
import threading
import time
from random import *

root = Tk()
root.configure(background='black')

root.attributes("-fullscreen", True)

class new_window:
    def build(self, delay, x, y):
        self.w = Tk()
        self.w.title("")
        self.ws = root.winfo_screenwidth() # width of the screen
        self.hs = root.winfo_screenheight() # height of the screen
        self.w.geometry(f"250x100+{int(round(self.ws/100*x))}+{int(round(self.hs/100*y))}")
        self.w.update()
        time.sleep(delay)
    def __init__(self, delay, x, y):
        threading.Thread(target=self.build(delay, x, y)).start()

def rdm(delay, count):  
    i = 1
    while i<=count:
        new_window(delay, randint(1, 100), randint(1, 100))
        i+=1
rdm(0.02, 100)

root.mainloop()
Toaster
  • 65
  • 6