0

So @furas I did what you told me. But still it didn't work. The screen freezes when opening the second window. I let the app = ... stay in if main and only made a variable of the second window to call over in the main file. I am reposting some of my code as you suggested for review. Thanks!

In the main.py:

   #pyttsx3 takes command
   elif 'game' in query:
        games_window_open = show_window("games", True)  #Checks if the game window is already running using win32 and returns False if not
    # For the first time games_window_open is False
    if games_window_open == False:
        second_window = UI_Games()

    elif games_window_open:
        self.ai_dialogue_update.emit("A game window is already open")
        speak("A game window is already open")

and in the second file:

from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton
from PyQt5 import uic
from PyQt5.QtCore import QThread
import sys

# Ignore the small classes. They are games that can be run in a thread from the ui second window that is listed below
class Snake(QThread):
    def start_game(self):
        import Games.sanke_game


class Space(QThread):
    def space(self):
        import Games.space_invader


class Target(QThread):
    def target(self):
        import Games.target_practice

#Second window is the UI_Games
class UI_Games(QMainWindow):
    def __init__(self):
        super(UI_Games, self).__init__()

        # Load the ui file
        uic.loadUi("Resources\\UI_files\\game_window_UI.ui", self)

        # Define our widgets
        self.snakeGame = self.findChild(QPushButton, "snakeGame")
        self.targetGame = self.findChild(QPushButton, "targetGame")
        self.guessGame = self.findChild(QPushButton, "guessGame")
        self.spaceGame = self.findChild(QPushButton, "spaceGame")
        self.ticTacToeGame = self.findChild(QPushButton, "ticTacToeGame")

        self.snakeGame.clicked.connect(lambda: self.game_choose("snake"))
        self.targetGame.clicked.connect(lambda: self.game_choose("target"))
        self.guessGame.clicked.connect(lambda: self.game_choose("guess"))
        self.spaceGame.clicked.connect(lambda: self.game_choose("space"))
        self.ticTacToeGame.clicked.connect(lambda: self.game_choose("tic-tac-toe"))

        
        # Show the app
        self.show()

    #Function to start the games
    def game_choose(self, choice):
        if choice == "target":
            self.space_worker = Target()
            self.space_worker.target()
        
        elif choice == "snake":
            self.snake_worker = Snake()
            self.snake_worker.start_game()

        elif choice == "guess":
            pass

        elif choice == "tic-tac-toe":
            pass

        elif choice == "space":
            space_worker = Space()
            space_worker.space()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    UIWindow = UI_Games()
    app.exec_()

Here's an image of the freezed screen: enter image description here

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • first window should run function with `UIWindow = UI()`. And you have to import second script in first script - but you have to remove `app =... ` `UIWindow = UI()`, `app.exec_()` from second script - or you have to put it in `if __name__ == "__main__":` – furas Oct 16 '22 at 20:58
  • @furas I don't know why but my main GUI stops responding. My main Gui handles a lot of work and has over 1000 lines of code, is it because of that. Also there's a QThread already running from the start. –  Oct 17 '22 at 12:45
  • @furas Basically I am running the GUI and an artificial assisstant (QThread) and want to open the Second window. –  Oct 17 '22 at 12:47
  • you have to run only one `app = QApplication(sys.argv)` and only one `app.exec_()` - and this is why second script need `if __name__ == "__main__":` – furas Oct 17 '22 at 13:18
  • @furas Please review the edited question –  Oct 17 '22 at 14:38
  • 1
    don't remove original question but append new information at the end of old question (eventually with text `**EDIT:**`) – furas Oct 17 '22 at 14:45
  • I see comment with `pyttsx3` in code - and maybe it blocks code in main window. – furas Oct 17 '22 at 14:48
  • Maybe first use `print()` (and `print(type(...))`, `print(len(...))`, etc.) to see which part of code is executed and what you really have in variables. It is called `"print debuging"` and it helps to see what code is really doing. maybe it will show in which line it stops code and window freeze. – furas Oct 17 '22 at 14:52
  • @furas I will keep **EDIT:** in mind. I have done print debuging and it seems that the GUI freezes after executing second_window = UI_Games() -->this line –  Oct 17 '22 at 14:59
  • problem can makes also your `QThread` - I thons you use it in wrong way. It may need to put code in function `QThread.run()` and later execute `QThread.start()` which will creat real thread in system and it will execute code from function `run()`. Your code can run it as normal function, not thread, and this can block all code. At least this is how it works with standard `threading.Thread` but `QThread` may need even more complex code. – furas Oct 17 '22 at 15:05
  • QThread also didn't work. I tried opening the window from a QThread but didn't work –  Oct 17 '22 at 16:06
  • I tried running the code from outside of any thread. Then an error occurred that is -- QBasicTimer::start: Timers cannot be started from another thread –  Oct 17 '22 at 16:07
  • I don't see any `QBasicTimer` in your code in question. I have no idea what you try to do. Better create new question on new page and add all code. We can't read in your mind - you have to describe all details in question. – furas Oct 17 '22 at 23:32

1 Answers1

1

It is minimal working code - and it doesn't matter if it uses file .ui or not.

It needs only one QApplication and only one exec()

Button runs function on_click() which runs self.second = SecondWindow() and this shows second window.

main.py

from PyQt5 import QtCore, QtWidgets


class FirstWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi()
        self.show()

    def setupUi(self):
        self.setWindowTitle("First")
        
        self.pushButton = QtWidgets.QPushButton("Open Second Window", parent=self)
        self.pushButton.clicked.connect(self.on_click)
        
        self.setCentralWidget(self.pushButton)

    def on_click(self):
        self.second = SecondWindow()


class SecondWindow(QtWidgets.QMainWindow):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi()
        self.show()
        
    def setupUi(self):
        self.setWindowTitle("Second")
        
        self.pushButton = QtWidgets.QPushButton("Close Window", parent=self)
        self.pushButton.clicked.connect(self.on_click)
        
        self.setCentralWidget(self.pushButton)

    def on_click(self):
        self.close()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    
    first = FirstWindow()
    
    app.exec()

You can put code in two separated file - but still you have to use only one QApplication and only one exec() (or second code has to use if __name__ == '__main__': to run QApplication and exec() only when it is directly executed but not when it is imported

main.py

from PyQt5 import QtCore, QtWidgets
from second import SecondWindow

class FirstWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi()
        self.show()

    def setupUi(self):
        self.setWindowTitle("First")
        
        self.pushButton = QtWidgets.QPushButton("Open Second Window", parent=self)
        self.pushButton.clicked.connect(self.on_click)
        
        self.setCentralWidget(self.pushButton)

    def on_click(self):
        self.second = SecondWindow()
        
if __name__ == "__main__":
    # it will skip this code when it will be imported to other script

    app = QtWidgets.QApplication([])
    
    first = FirstWindow()
    
    app.exec()

second.py

from PyQt5 import QtCore, QtWidgets

class SecondWindow(QtWidgets.QMainWindow):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi()
        self.show()
        
    def setupUi(self):
        self.setWindowTitle("Second")
        
        self.pushButton = QtWidgets.QPushButton("Close Window", parent=self)
        self.pushButton.clicked.connect(self.on_click)
        
        self.setCentralWidget(self.pushButton)

    def on_click(self):
        self.close()

if __name__ == "__main__":
    # it will skip this code when it will be imported to other script

    app = QtWidgets.QApplication([])
    
    second = SecondWindow()
    
    app.exec()
furas
  • 134,197
  • 12
  • 106
  • 148