I have my QMainWindow set up as the code below shows. I have my menu include "New" and "Quit" menu items (see the image). I successfully coded the Quit one, which was too easy for me. All I want is to open a new instance of my main application when I click the "New" menu item (shown in the image).
class MainApp(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.show()
self.action_Quit.triggered.connect(self.exit_app)
def exit_app(self):
self.close()
app = QApplication(sys.argv)
MainWindow = MainApp()
sys.exit(app.exec())
Creating a new window is just a matter of creating a new instance of it (which is the class of self
if you want to create a new instance of the same type).
The actual issue is keeping references of those windows. If you create a new window without keeping a persistent reference to it, it will be probably destroyed due to the garbage collection of Python (or because no C++ reference is kept, which usually means using a parent QObject).
If you plan to have multiple windows of the same type, you need to use a common container. To achieve this, there are multiple solutions, but the concept remains: you need a "controller" that can always have pointers to those windows.
For complex applications, this usually means that the "controller" is a main object that normally exists within the program itself. A common way to do so is by subclassing QApplication and create a data container (even a basic python list) that keeps track of the windows.
A simpler solution could use a list of those window as a class attribute of the window class itself.
In the following example, the CommonWindow
class has a list set as class attribute that keeps track of the existing windows and eventually adds/removes them when they're created or closed. For explanation reasons, I implemented a basic QListWidget that will be constantly updated with the current list of existing windows, adding them when new windows are created, and removing them when they're closed.
from PyQt5.QtWidgets import *
class CommonWindow(QMainWindow):
winIndex = 0
siblingWindows = []
def __init__(self):
super().__init__()
# note: this sets a *class* attribute that always increases the count
CommonWindow.winIndex += 1
self.setWindowTitle('Window {}'.format(self.winIndex))
self.siblingWindows.append(self)
menu = self.menuBar().addMenu('File')
newAction = menu.addAction('New window')
quitAction = menu.addAction('Quit')
self.windowList = QListWidget()
self.setCentralWidget(self.windowList)
newAction.triggered.connect(self.newWindow)
quitAction.triggered.connect(QApplication.quit)
if len(self.siblingWindows) == 1:
# avoid unnecessary calls
self.updateWindowList()
def newWindow(self):
new = CommonWindow()
new.show()
for win in self.siblingWindows:
win.updateWindowList()
def updateWindowList(self):
self.windowList.clear()
for win in self.siblingWindows:
self.windowList.addItem(win.windowTitle())
def closeEvent(self, event):
self.siblingWindows.remove(self)
for win in self.siblingWindows:
win.updateWindowList()
app = QApplication([])
test = CommonWindow()
test.show()
app.exec()