2
votes

La fenêtre PyQt5 ne s'ouvre pas sur show () lorsque la fenêtre parent est spécifiée

J'ai défini une fenêtre principale simple et une seconde fenêtre pop-up. Lorsque j'appelle la méthode MainWindow.create_new_window (), SecondWindow n'apparaît pas comme une nouvelle fenêtre mais son QLabel est créé dans l'instance MainWindow. Voici le 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_())

Lorsque je crée la deuxième fenêtre sans spécifier l'instance MainWindow comme parent ( self.second_window = SecondWindow () ), elle s'ouvre comme prévu . Quelqu'un peut-il me dire ce qui se passe ici?


0 commentaires

3 Réponses :


-1
votes

Dans vos packages importés, importez cette équipe:

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


1 commentaires

Toutes mes importations sont correctes. Je les ai laissés de côté parce que je pensais que c'était explicite, mon erreur. Je vais éditer la question.



1
votes

Par défaut, un QWidget qui a un parent implique que le widget sera placé à l'intérieur du parent, donc vous observez ce comportement.

Si vous voulez que ce soit une fenêtre, vous devez activer le drapeau 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) # <---
# ...

Une autre option consiste à utiliser un QDialog qui est un type de widget qui par défaut a déjà ce drapeau activé et dont l'objectif est de demander des informations à l'utilisateur.


2 commentaires

Excellent merci. Je savais que je manquais quelque chose, mais je ne pouvais pas trouver quoi.


Je vous recommande de vérifier l'exemple suivant doc.qt.io/qt -5 / qtwidgets-widgets-windowflags-example.html , si vous souhaitez voir la version en python, téléchargez le code source de pyqt5 et vérifiez le fichier examples / widgets / windowflags.py



1
votes

De la documentation:

Si parent vaut 0, le nouveau widget devient une fenêtre. Si parent est un autre widget, ce widget devient une fenêtre enfant à l'intérieur du parent. Le nouveau widget est supprimé lorsque son parent est supprimé.

Quand j'exécute votre code, j'obtiens ce nouveau widget à l'intérieur du widget principal - comme décrit dans la documentation.

Donc, fondamentalement, vous devriez définir parent sur un QWidget uniquement si vous avez l'intention de l'utiliser comme widget de fenêtre (insérez-le dans une mise en page, ou utilisez-le comme widget central etc.); si vous voulez l'utiliser tel quel, vous n'avez pas besoin d'un parent.

Si vous avez besoin que votre widget ait un parent et soit une fenêtre séparée, la meilleure idée peut être d'utiliser QDialog au lieu de QWidget . Créez simplement votre sous-classe de classe SecondWindow QDialog à la place et vous êtes prêt à partir.

Exemple de code (j'ai changé vos deux Windows en 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_())


4 commentaires

J'ai besoin du parent. Mon objectif final est d'avoir une fenêtre enfant qui est WindowModal, ce qui signifie qu'elle bloque l'interaction avec sa fenêtre parente.


Votre solution serait alors probablement meilleure avec QMainWindow au lieu de QDialog / QWidget . Dans ce cas (comme écrit), vous devez ajouter self.setModal (True) dans create_new_window () . J'ai mis à jour ma réponse pour ajouter une deuxième modalité de fenêtre.


self.setModal () est inutile s'il n'apparaît pas comme une nouvelle fenêtre en premier lieu.


Ma réponse est basée sur votre code - je viens de changer les deux fenêtres en sous-classes QDialog là où cela fonctionne.