Перехват закрытия дочернего окна

Есть функция test() запускающая дочернее окно, экземпляр класса которого называется tla.
Вопрос как перехватить закрытие этого дочернего окна при нажатии на крестик?

Попытка перехвата через создание в функции метода closeEvent ничего не дает. При этом закрытие главного окна перехватывается из функции closeEvent в классе MainWindow.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from PyQt5 import QtWidgets, QtCore, QtGui
import sys, os, time


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self,parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        ss = MyWindow()
        self.setCentralWidget(ss)
        
    def closeEvent(self, e):
        print("Main close")
        e.accept()
        QtWidgets.QWidget.closeEvent(self, e)
        
        
class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.makeWidget()
        
    def makeWidget(self):
        self.vbox = QtWidgets.QVBoxLayout()
        self.label = QtWidgets.QLabel('Click button')
        self.button = QtWidgets.QPushButton('new window')
        self.button.clicked.connect(self.test)
        self.vbox.addWidget(self.label)
        self.vbox.addWidget(self.button)
        self.setLayout(self.vbox)
        
    def test(self):
        def getName():
            #...anything doing...
            tla.close()
            
        def closeEvent(tla, e):
                print('closing tla')
                e.accept()
                QtWidgets.QWidget.closeEvent(tla,e)
        
        tla = QtWidgets.QWidget(parent=window, flags=QtCore.Qt.Window)
        tla.setWindowTitle('Тест')
        tlavbox = QtWidgets.QVBoxLayout()
        lE_key = QtWidgets.QLineEdit()
        btn2 = QtWidgets.QPushButton('Добавить')
        btn3 = QtWidgets.QPushButton('Закрыть')
        btn2.clicked.connect(getName)
        btn3.clicked.connect(tla.close)
        hbox = QtWidgets.QHBoxLayout()
        hbox.addWidget(btn2)
        hbox.addWidget(btn3)
        tlavbox.addWidget(lE_key)
        tlavbox.addLayout(hbox)
        tla.setLayout(tlavbox)
        tla.show()



if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.setWindowTitle('Title')
    window.show()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: S. Nick

Я не уверен, что правильно вас понимаю, но попробуйте так:

import sys
# ???import os
# ???import time
from PyQt5 import QtWidgets, QtCore, QtGui

        
class TlaWindow(QtWidgets.QWidget):
    def __init__(self, parent=None): 
        super(TlaWindow, self).__init__(parent)
        
        self.setWindowFlags(QtCore.Qt.Window)   
        self.setWindowTitle('TlaWindow')
        self.parent = parent

        self.lE_key = QtWidgets.QLineEdit()
        btn2 = QtWidgets.QPushButton('Добавить')
        btn2.clicked.connect(self.getName)
        btn3 = QtWidgets.QPushButton('Закрыть')
        btn3.clicked.connect(self.close_TlaWindow)
        
        hbox = QtWidgets.QHBoxLayout()
        hbox.addWidget(btn2)
        hbox.addWidget(btn3)
        
        tlavbox = QtWidgets.QVBoxLayout(self)        
        tlavbox.addWidget(self.lE_key)
        tlavbox.addLayout(hbox)
        
        self.flag_close = False                                    # !!! +++

    def getName(self):
        #...anything doing...
        self.parent.label.setText(self.lE_key.text())
        self.flag_close = True                                     # !!! +++
        self.close()
        
    def close_TlaWindow(self):
        self.flag_close = True                                     # !!! +++
        self.close()

    def closeEvent(self, e):                                       # !!! +++
        if self.flag_close:                                        # !!! +++
            e.accept()
        else:
            e.ignore()


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.centralWidget = QtWidgets.QWidget()
        self.setCentralWidget(self.centralWidget)

        self.label = QtWidgets.QLabel('Click button')
        self.button = QtWidgets.QPushButton('new window')
        self.button.clicked.connect(self.test)

        self.vbox = QtWidgets.QVBoxLayout(self.centralWidget)        
        self.vbox.addWidget(self.label)
        self.vbox.addWidget(self.button)

    def test(self):
        self.tlaWindow = TlaWindow(self)
        self.tlaWindow.show()
    
    def closeEvent(self, e):
        self.tlaWindow.hide()
        print("Main close")
        e.accept()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.setWindowTitle('Title')
    window.show()
    sys.exit(app.exec_())

введите сюда описание изображения

введите сюда описание изображения


Update:

с вашим кодом все нормально, но в вашем коде окно tla является экземпляром класса TlaWindow, фактически он является главным окном хоть технически и запускается из MainWindow. Мне же в моем коде нужно перехватить окно Tla которое, не является экземпляром отдельного класса, а запускается окном ss которое и является экземпляром отдельного класса MyWindow

Я все равно плохо понимаю то, что вы хотите сделать.

Если вам нужно скрыть или показать кнопку закрытия, более удобно использовать WindowCloseButtonHint.

import sys
from PyQt5 import QtWidgets, QtCore, QtGui

       
class MyWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        
        self.makeWidget()
        
    def makeWidget(self):
        self.label = QtWidgets.QLabel('Click button')
        self.button = QtWidgets.QPushButton('new window')
        self.button.clicked.connect(self.test)
        
        self.vbox = QtWidgets.QVBoxLayout(self)        
        self.vbox.addWidget(self.label)
        self.vbox.addWidget(self.button)
        
    def test(self):
        def getName():
            print(f'##...anything doing...') 
            tla.close()
        '''    
        def closeEvent(tla, e):
            print('closing tla')
            e.accept()
            QtWidgets.QWidget.closeEvent(tla, e)
        '''
        tla = QtWidgets.QWidget(parent=window)            #, flags=QtCore.Qt.Window)

        tla.setWindowFlags(self.windowFlags() 
            & ~QtCore.Qt.WindowCloseButtonHint                         # !!! +++
            | QtCore.Qt.Window
        )                
        
        tla.setWindowTitle('Тест')
        tlavbox = QtWidgets.QVBoxLayout()
        lE_key = QtWidgets.QLineEdit()
        btn2 = QtWidgets.QPushButton('Добавить')
        btn3 = QtWidgets.QPushButton('Закрыть')
        btn2.clicked.connect(getName)
        btn3.clicked.connect(tla.close)
        hbox = QtWidgets.QHBoxLayout()
        hbox.addWidget(btn2)
        hbox.addWidget(btn3)
        tlavbox.addWidget(lE_key)
        tlavbox.addLayout(hbox)
        tla.setLayout(tlavbox)
        tla.show()


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        
        ss = MyWindow()
        self.setCentralWidget(ss)
        
    def closeEvent(self, e):
        print("- Main close")
        e.accept()
        QtWidgets.QWidget.closeEvent(self, e)
        

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.setWindowTitle('Title')
    window.show()
    sys.exit(app.exec_())

введите сюда код

→ Ссылка