从 QDockWidget 附加和分离外部应用程序时的问题 [英] Issues when attaching and detaching external app from QDockWidget
问题描述
考虑一下这段代码:
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.目前,代码有两个重要问题.
The goal here is to fix the code so the window attaching/detaching into a QDockWidget will be made properly. Right now, the code has 2 important issues.
原来窗口的样式搞砸了:
Style of the original window is screwed up:
a) 附加前(计算器有菜单栏)
a) Before attaching (the calculator has a menu bar)
b) 附加后(计算器菜单栏不见了)
b) When attached (the calculator menu bar is gone)
c) 分离时(菜单栏没有正确恢复)
c) When detached (the menu bar hasn't been restored properly)
我已经尝试过使用 flags/setFlags qt 函数或 getWindowLong/setWindowLong 但我的所有尝试都没有成功
I've already tried using flags/setFlags qt functions or getWindowLong/setWindowLong but I haven't had luck with all my attempts
如果您已经将计算器附加和分离到主窗口,然后您决定关闭主窗口,那么您肯定希望所有内容(pyqt 进程)都被正确关闭和清理.现在,情况并非如此,为什么?
If you have attached and detached the calculator to the mainwindow, and then you decide to close the mainwindow, you definitely want everything (pyqt process) to be closed and cleaned properly. Right now, that won't be the case, why?
实际上,当您将计算器附加/分离到主窗口时,python 进程将保持,您需要手动强制终止进程(即 ctrl+break conmu,ctrl+c cmd 提示符)...这表明代码在为人父母/去父母时没有正确做事
In fact, when you've attached/detached the calculator to the mainwindow, the python process will hold and you'll need to force the termination of the process manually (i.e. ctrl+break conemu, ctrl+c cmd prompt)... which indicates the code is not doing things correctly when parenting/deparenting
附加说明:
- http://doc.qt.io/qt-5/qwindow.html#fromWinId
- http://doc.qt.io/qt-5/qwidget.html#createWindowContainer
- 在上面的最小代码中,我将 calc.exe 作为子进程生成,但您可以假设 calc.exe 是一个现有的非子进程,例如
explorer.exe
推荐答案
我发现部分问题需要关闭.因此,当您在 attach
函数中创建 self._window
并关闭 MainWindow
时,该其他窗口(线程)仍处于静止状态.因此,如果您在 __init__
函数中添加 self._window = None
并添加如下 __del__
函数,则该部分是固定的.仍然不确定缺少菜单.我还建议使用 self.__p
保持子进程句柄,而不是放手.也将其包含在 __del__
中.
I found part of the issue wrt to closing. So when you are creating the self._window
in the attach
function and you close the MainWindow
, that other window (thread) is sitting around still. So if you add a self._window = None
in the __init__
function and add a __del__
function as below, that part is fixed. Still not sure about the lack of menu. I'd also recommend holding onto the subprocess handle with self.__p
instead of just letting that go. Include that in the __del__
as well.
def __del__(self):
self.__p.terminate()
if self._window:
print('terminating window')
self._window.close
可能更好的是包含一个 closeEvent
Probably better yet would be to include a closeEvent
def closeEvent(self, event):
print('Closing time')
self.__p.terminate()
if self._window is not None:
print('terminating window')
self._window.close
这篇关于从 QDockWidget 附加和分离外部应用程序时的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!