从QDockWidget连接和分离外部应用程序时出现的问题

BPL*_*BPL 15 python windows qt pyqt

考虑一下这段代码:

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_())
Run Code Online (Sandbox Code Playgroud)

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

Issue1

原始窗口的样式搞砸了:

a)连接前(计算器有菜单栏)

在此输入图像描述

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

在此输入图像描述

c)分离时(菜单栏未正确恢复)

在此输入图像描述

我已经尝试过使用flags/setFlags qt函数或getWindowLong/setWindowLong位我没有运气我所有的尝试

Issue2

如果您已将计算器连接到主窗口并将其分离,然后您决定关闭主窗口,那么您肯定希望关闭并正确清理所有内容(pyqt进程),现在情况并非如此,为什么?

事实上,当你将计算器连接/分离到主窗口时,python进程将保持并且你需要手动强制终止进程(即:ctrl + break conemu,ctrl + c cmd prompt)...这表示代理在父母/父母身份时没有正确地执行操作

补充说明:

Tom*_*tyn 1

我发现问题的一部分需要关闭。self._window因此,当您在函数中创建attach并关闭 时MainWindow,另一个窗口(线程)仍然处于静止状态。self._window = None因此,如果您在函数中添加 a__init__并添加__del__如下函数,则该部分是固定的。仍然不确定是否缺少菜单。我还建议保留子进程句柄self.__p而不是放手。也将其包括在内__del__

    def __del__(self):
        self.__p.terminate()
        if self._window:
            print('terminating window')
            self._window.close
Run Code Online (Sandbox Code Playgroud)

可能更好的是包括一个closeEvent

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