代码之家  ›  专栏  ›  技术社区  ›  BPL

从QDockWidget附加和分离外部应用程序时出现问题

  •  9
  • BPL  · 技术社区  · 7 年前

    import subprocess
    import win32gui
    import win32con
    import time
    import sys
    from PyQt5.Qt import *  # noqa
    
    
    class Mcve(QMainWindow):
    
        def __init__(self, path_exe):
            super().__init__()
    
            menu = self.menuBar()
    
            attach_action = QAction('Attach', self)
            attach_action.triggered.connect(self.attach)
            menu.addAction(attach_action)
    
            detach_action = QAction('Detach', self)
            detach_action.triggered.connect(self.detach)
            menu.addAction(detach_action)
    
            self.dock = QDockWidget("Attach window", self)
            self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
    
            p = subprocess.Popen(path_exe)
            time.sleep(0.5)  # Give enough time so FindWindowEx won't return 0
            self.hwnd = win32gui.FindWindowEx(0, 0, "CalcFrame", None)
            if self.hwnd == 0:
                raise Exception("Process not found")
    
        def detach(self):
            try:
                self._window.setParent(None)
                # win32gui.SetWindowLong(self.hwnd, win32con.GWL_EXSTYLE, self._style)
                self._window.show()
                self.dock.setWidget(None)
                self._widget = None
                self._window = None
            except Exception as e:
                import traceback
                traceback.print_exc()
    
        def attach(self):
            # self._style = win32gui.GetWindowLong(self.hwnd, win32con.GWL_EXSTYLE)
            self._window = QWindow.fromWinId(self.hwnd)
            self._widget = self.createWindowContainer(self._window)
            self.dock.setWidget(self._widget)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = Mcve("C:\\Windows\\system32\\calc.exe")
        w.show()
        sys.exit(app.exec_())
    

    这里的目标是修复代码,这样就可以正确地将窗口附加/分离到QDockWidget中。现在,代码有两个重要问题。

    问题1

    原来窗户的样式是乱七八糟的:

    a) 附加之前(计算器有一个菜单栏)

    enter image description here

    b) 连接后(计算器菜单栏消失)

    enter image description here

    enter image description here

    我已经尝试过使用flags/setFlags qt函数或getWindowLong/setWindowLong,但是我的所有尝试都没有成功

    问题2

    实际上,当您将计算器附加/分离到主窗口时,python进程将保持不变,您需要手动强制终止进程(即ctrl+break conemu,ctrl+c cmd prompt)。。。这表示代码在为人父母/解除父母关系时没有正确执行操作

    附加说明:

    0 回复  |  直到 5 年前
        1
  •  1
  •   Tom Myddeltyn    5 年前

    我发现有一部分问题与结案无关。所以当你创建 self._window attach 函数并关闭 MainWindow ,另一个窗口(线程)静止不动。如果你加上 self._window = None __init__ 函数并添加 __del__ 功能如下,该部分是固定的。还是不确定菜单有没有。我还建议使用 self.__p 而不是就此罢休。把它包括在 __德尔__ 也。

        def __del__(self):
            self.__p.terminate()
            if self._window:
                print('terminating window')
                self._window.close
    

    也许更好的办法是加入 closeEvent

        def closeEvent(self, event):
            print('Closing time')
            self.__p.terminate()
            if self._window is not None:
                print('terminating window')
                self._window.close