1

I am trying to create a program that has a tkinter window open, and then when you push a button, it closes the tkinter window and opens a pygame window. However, when I click the button to open the pygame window, it opens the pygame window and the tkinter window stays open.

Code:

import tkinter as tk
import pygame

root = tk.Tk()
btn = tk.Label(root, text="Start")
btn.bind("<Button-1>", lambda x: root.quit())
btn.pack()

root.mainloop()
root.destroy()

win = pygame.display.set_mode((500, 500))
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    win.fill((255, 255, 255))
    pygame.display.update()
pygame.quit()

I have also tried using:

btn.bind("<Button-1>", lambda x: root.destroy())
btn.bind("<Button-1>", root.quit)
btn.bind("<Button-1>", root.destroy)
btn.bind("<Button-1>", lambda: root.quit())
btn.bind("<Button-1>", lambda: root.destroy())
def start(event=None):
    root.quit()
btn.bind("<Button-1>", start)

How can I fix this? (I'm running Python 3.7.7 on MacOS 11.1)

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
AlarmClockMan
  • 470
  • 2
  • 16

2 Answers2

0

I cannot reproduce the issue. However I recommend to use the tkinter window to a function or class. Call destroy when the key is pressed rather than after the main loop exits. Invoking the destroy command will cause and error if the application has already been destroyed, for example if the window is closed manually.

import tkinter as tk
import pygame

def runTk():
    root = tk.Tk()
    btn = tk.Label(root, text="Start")
    btn.bind("<Button-1>", lambda x: root.destroy())
    btn.pack()
    root.mainloop()

runTk()

win = pygame.display.set_mode((500, 500))
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    win.fill((255, 255, 255))
    pygame.display.update()
pygame.quit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • I still get the same issue using this code. – AlarmClockMan Jan 24 '21 at 19:02
  • In general the code should work. See [Function to close the window in Tkinter](https://stackoverflow.com/questions/8009176/function-to-close-the-window-in-tkinter). The issue appears t o be related to your system (macOS) – Rabbid76 Jan 24 '21 at 19:07
0

I tried organising your code in a class, so it is a bit easier to make modifications to it and calling the individual components.

Aside of that, I changed your btn to use tk.Button instead of tk.Label (thought it made more sense in the context)

The actual toggle function calls the self.tk_root.withdraw() command. This effectively hides the root tk window - you can make it appear again by calling self.tk_root.deiconify(). If you also wish to destroy the root after you have hidden it, you can simply add a self.tk_root.destroy() after the withdraw.

Edit: If withdraw() isn't working for you, try to use iconify() instead.

import tkinter as tk
import pygame


class TkPygame:
    def __init__(self):
        self.tk_root = tk.Tk()

        self.make_tk_widgets()

        self.tk_root.mainloop()

    def make_tk_widgets(self):
        btn = tk.Button(self.tk_root, text='Start', command=self.toggle_to_pygame)
        btn.pack()

    def toggle_to_pygame(self):
        self.tk_root.withdraw()
        self.make_pygame_window()

    def make_pygame_window(self):
        pygame_root = pygame.display.set_mode((500, 500))
        run = True
        while run:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
            pygame_root.fill((255, 255, 255))
            pygame.display.update()
        pygame.quit()


TkPygame()
oskros
  • 3,101
  • 2
  • 9
  • 28
  • When I run `iconify()` (`withdraw()` didn't work), the window is minimized, and then immediately _unminimized_, and the pygame window is opened. When I call `self.tk_root.destroy()` after that, it does nothing. Any ideas on how to fix this? – AlarmClockMan Jan 24 '21 at 23:40
  • No sorry dont know why that wouldnt work for your, i cannot replicate the issue. I read a bit more about it, and it seems to be a known issue on OS X that you cannot destroy/quit the root without actually closing python altogether with something like `sys.exit()` – oskros Jan 25 '21 at 08:03