Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Is there have relationship between QWidget and QWindow after QWindow detach from QWidget?



  • Steps:

    1. Start application A.
    2. Start application B.
    3. Click embed button in application B. Embed the application A to application B.
    4. Click popup button. Popup the application A.
    5. Click block button in application A. Application A run Infinite loop, can not respond to mouse operations.
    6. Application B's process also cannot respond to mouse operations.

    What's the reason?

    Application B code:

    # -*- coding: utf-8 -*-
    
    import sys
    import win32gui
    from PyQt5.QtGui import QWindow
    from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QHBoxLayout, QPushButton
    from PyQt5.QtCore import Qt
    
    
    class MyWidget(QWidget):
        def __init__(self, parent=None):
    	super(MyWidget, self).__init__(parent)
    	layout = QVBoxLayout(self)
    	btnLayout = QHBoxLayout()
    	embedBtn = QPushButton("embed")
    	popupBtn = QPushButton("popup")
    	btnLayout.addWidget(embedBtn)
    	btnLayout.addWidget(popupBtn)
    	layout.addLayout(btnLayout)
    
    	embedBtn.clicked.connect(self.embed)
    	popupBtn.clicked.connect(self.popup)
    
    	self.window = None
    	self.windowWidget = None
    	self.hwnd = None
            self.resize(400, 400)
    
        def embed(self):
    	# todo application title must be right
    	self.hwnd = win32gui.FindWindow(None, "block application")
    	if self.hwnd:
    		self.window = QWindow.fromWinId(self.hwnd)
    		self.windowWidget = QWidget.createWindowContainer(self.window)
    		self.layout().addWidget(self.windowWidget)
    		win32gui.SetParent(self.hwnd, int(self.winId()))
    
        def popup(self):
    	self.window.setParent(None)
    	self.window.setFlags(Qt.Window)
    	self.windowWidget.setParent(None)
    	self.windowWidget.destroy()
    	win32gui.SetParent(self.hwnd, 0)
    	win32gui.UpdateWindow(self.hwnd)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        widget = MyWidget()
        widget.show()
        app.exec_()
    

    Application A code:

    # -*- coding: utf-8 -*-
    
    import sys
    from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton
    
    
    class MyWidget(QWidget):
        def __init__(self, parent=None):
            super(MyWidget, self).__init__(parent)
            self.setWindowTitle("block application")
            layout = QVBoxLayout(self)
            blockBtn = QPushButton("block process")
            layout.addWidget(blockBtn)
    
            blockBtn.clicked.connect(self.block)
            self.resize(300, 200)
    
        def block(self):
            import time
            while True:
    	    print(time.time())
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        widget = MyWidget()
        widget.show()
        app.exec_()


  • The environment:
    Python 3.6.8
    PyQt 5.7.1
    pywin32-224-cp36-cp36m-win_amd64


  • Lifetime Qt Champion

    Hi,

    @richie18 said in Is there have relationship between QWidget and QWindow after QWindow pop up?:

    Block the application A by manual.

    What do you mean by that ?



  • @SGaist said in Is there have relationship between QWidget and QWindow after QWindow pop up?:

    lock the application A by manua

    Block the application A's process after application A pop up from application B. For example, run code in application A below:

    import time
    while True:
        print(time.time())


  • @SGaist

    Use code below as application A.
    When application A is poped up, click the 'block process' button in applicaiton A. Then application B's process is also blocked.

    # -*- coding: utf-8 -*-
    
    import sys
    from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QPushButton
    
    
    class MyWidget(QWidget):
        def __init__(self, parent=None):
    	super(MyWidget, self).__init__(parent)
    	self.setWindowTitle("block application")
    	layout = QVBoxLayout(self)
    	blockBtn = QPushButton("block process")
    	layout.addWidget(blockBtn)
    
    	blockBtn.clicked.connect(self.block)
    	self.resize(300, 200)
    
        def block(self):
    	import time
    	while True:
    		print(time.time())
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        widget = MyWidget()
        widget.show()
        app.exec_()

  • Lifetime Qt Champion

    Intriguing... Out of curiosity, what is the use case of "blocking" the application ?



  • @SGaist

    Maybe I am not expressing correctly.
    “blocking” Means that application cannot respond to mouse operations

    May be follow the steps below to make it clear.

    Steps:

    1. Start application A.
    2. Start application B.
    3. Click embed button in application B. Embed the application A to application B.
    4. Click popup button. Popup the application A.
    5. Click block button in application A. Application A run Infinite loop, can not respond to mouse operations.
    6. Application B's process also cannot respond to mouse operations.

  • Lifetime Qt Champion

    I would try to check with the event dispatchers if you can find something there.



  • @SGaist

    Application A's block() add code processEvents(), it seems ok. But native windows cannot be handled this way.
    So, I'm not sure relationship between two application when they are detached. And how to solve?

    def block(self):
        import time
        while True:
    	print(time.time())
            QApplication.processEvents()

  • Lifetime Qt Champion

    You should check the the win32gui module developer, he may have some insight as to what is happening.



  • @SGaist

    I'm not use win32gui.setParent(), also has this problem.


  • Lifetime Qt Champion

    As already suggested, contact the module author.


Log in to reply