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

时间:2019-01-27 13:33:50

标签: 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_())

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

问题1

原始窗口的样式被弄乱了:

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

enter image description here

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

enter image description here

c)分离时(菜单栏未正确还原)

enter image description here

我已经尝试过使用flags / setFlags qt函数或getWindowLong / setWindowLong位,但我的尝试还不够运气

问题2

如果您已经将计算器连接到主窗口并从其上拆下,然后决定关闭主窗口,则您肯定希望所有东西(pyqt进程)都被正确地关闭和清理,现在不是这种情况了,为什么?< / p>

实际上,在将计算器连接/分离到主窗口后,Python进程将挂起,并且您需要手动强制终止进程(即:ctrl + break锥体,ctrl + c cmd提示符) ...表示在父母/父母抚养父母时,代码工作不正确

其他说明:

1 个答案:

答案 0 :(得分:0)

我发现部分问题要解决。因此,当您在self._window函数中创建attach并关闭MainWindow时,另一个窗口(线程)仍然静止不动。因此,如果您在self._window = None函数中添加__init__并按如下所示添加__del__函数,则该部分是固定的。仍然不确定缺少菜单。我还建议您使用self.__p握住子进程句柄,而不要放任其走。还应将其包括在__del__中。

    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