Ian Kent
Ian Kent

Reputation: 791

PyQt5 window not opening on show() when parent window is specified

I have defined a simple main window and second pop-up window. When I call the MainWindow.create_new_window() method, the SecondWindow does not show up as a new window but its QLabel is created within the MainWindow instance. Here's the code:

import sys

from PyQt5.QtWidgets import QApplication, QPushButton, QLabel, QWidget, QVBoxLayout

class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.second_window = None

        self.main_layout = QVBoxLayout(self)

        self.new_window_button = QPushButton('New Window', self)
        self.new_window_button.clicked.connect(self.create_new_window)

        self.main_layout.addWidget(self.new_window_button)

    def create_new_window(self):
        if self.second_window is None:
            self.second_window = SecondWindow(self)
        self.second_window.show()


class SecondWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super(SecondWindow, self).__init__(*args, **kwargs)

        self.main_layout = QVBoxLayout(self)

        self.hello_label = QLabel('Hello I am the second window.', self)

        self.main_layout.addWidget(self.hello_label)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainwin = MainWindow()
    mainwin.show()
    sys.exit(app.exec_())

When I create the second window without specifying the MainWindow instance as the parent (self.second_window = SecondWindow()), it opens as expected. Can anyone tell me what's going on here?

Upvotes: 2

Views: 2733

Answers (3)

icwebndev
icwebndev

Reputation: 413

From documentation:

If parent is 0, the new widget becomes a window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted.

When I run your code, I get that new widget inside of the main one - as is described in documentation.

So basically, you should set parent to a QWidget only if you indend to use it as a window's widget (insert it in a layout, or use it as central widget etc.); if you want to use it as-is you don't need a parent.

If you need your widget to have a parent and be a separate window, better idea may be to use QDialog instead of QWidget. Just make your SecondWindow class subclass QDialog instead and you're good to go.

Example code (I've changed both your Windows to QDialog):

from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QApplication, QDialog
class MainWindow(QDialog):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.second_window = None

        self.main_layout = QVBoxLayout(self)

        self.new_window_button = QPushButton('New Window', self)
        self.new_window_button.clicked.connect(self.create_new_window)

        self.main_layout.addWidget(self.new_window_button)

    def create_new_window(self):
        if self.second_window is None:
            self.second_window = SecondWindow(self)
        # set second window as modal, because MainWindow is QDialog/QWidget.
        self.setModal(True)
        self.second_window.show()


class SecondWindow(QDialog):
    def __init__(self, *args, **kwargs):
        super(SecondWindow, self).__init__(*args, **kwargs)

        self.main_layout = QVBoxLayout(self)

        self.hello_label = QLabel('Hello I am the second window.', self)

        self.main_layout.addWidget(self.hello_label)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainwin = MainWindow()
    mainwin.show()
    sys.exit(app.exec_())

Upvotes: 1

eyllanesc
eyllanesc

Reputation: 244262

By default, a QWidget that has a parent implies that the widget will be placed inside the parent, so you observe that behavior.

If you want it to be a window then you must activate the flag Qt::Window

# ...
from PyQt5.QtCore import Qt

# ...
class SecondWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super(SecondWindow, self).__init__(*args, **kwargs)
        self.setWindowFlags(self.windowFlags() | Qt.Window) # <---
# ...

Other options is to use a QDialog that is a type of widget that by default already has that flag activated and whose objective is to ask the user for information.

Upvotes: 1

Ziya Arslan
Ziya Arslan

Reputation: 131

In your imported packages import that staff:

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel

Upvotes: -1

Related Questions