I should also point out that embedding external, third-party windows is not officially supported by Qt. The createWindowContainer function is only intended to work with Qt window IDs, so the behaviour with foreign window IDs is strictly undefined (see: QTBUG-44404). The various issues are documentented in this wiki article: Qt and foreign windows. In particular, it states:我们当前的API还有一个更大的问题,尚未讨论,QWindow :: fromWinId()返回QWindow指针的事实,从API合同的角度来看,应该支持任何任何其他QWindow支持,包括使用setter来操作窗口,并连接到信号以观察窗口的变化.A larger issue with our current APIs, that hasn't been discussed yet,is the fact that QWindow::fromWinId() returns a QWindow pointer, whichfrom an API contract point of view should support any operation thatany other QWindow supports, including using setters to manipulate thewindow, and connecting to signals to observe changes to the window.我们的任何平台在实践中均未遵守本合同,而且QWindow :: fromWinId()的文档没有提到关于情况的任何事情.This contract is not adhered to in practice by any of our platforms,and the documentation for QWindow::fromWinId() doesn't mentionanything about the situation.这种未定义/平台特定行为的原因在很大程度上归结为我们对平台的完全控制本机窗口句柄,而本机窗口句柄通常是本机窗口句柄类型的子类,我们在其中实现回调和其他逻辑.替换本机窗口句柄时我们无法控制的实例,并且无法实现我们的实例回调逻辑,行为变得不确定并且充满漏洞与常规的QWindow相比.The reasons for this undefined/platform specific behaviour largelyboils down to our platforms relying on having full control of thenative window handle, and the native window handle often being asubclass of the native window handle type, where we implementcallbacks and other logic. When replacing the native window handlewith an instance we don't control, and which doesn't implement ourcallback logic, the behaviour becomes undefined and full of holescompared to a regular QWindow.因此,在设计依赖于此功能的应用程序时,请牢记所有这些,并相应地调整您的期望...So, please bear all that in mind when designing an application that relies on this functionality, and adjust your expectations accordingly... 演示脚本:import sys, os, shutilfrom PySide2.QtCore import ( Qt, QProcess, QTimer, )from PySide2.QtGui import ( QWindow, )from PySide2.QtWidgets import ( QApplication, QWidget, QVBoxLayout, QMessageBox, )class Window(QWidget): def __init__(self, program, arguments): super().__init__() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.external = QProcess(self) self.external.start(program, arguments) self.wmctrl = QProcess() self.wmctrl.setProgram('wmctrl') self.wmctrl.setArguments(['-lpx']) self.wmctrl.readyReadStandardOutput.connect(self.handleReadStdOut) self.timer = QTimer(self) self.timer.setSingleShot(True) self.timer.setInterval(25) self.timer.timeout.connect(self.wmctrl.start) self.timer.start() self._tries = 0 def closeEvent(self, event): for process in self.external, self.wmctrl: process.terminate() process.waitForFinished(1000) def embedWindow(self, wid): window = QWindow.fromWinId(wid) widget = QWidget.createWindowContainer( window, self, Qt.FramelessWindowHint) self.layout().addWidget(widget) def handleReadStdOut(self): pid = self.external.processId() if pid > 0: windows = {} for line in bytes(self.wmctrl.readAll()).decode().splitlines(): columns = line.split(maxsplit=5) # print(columns) # wid, desktop, pid, wmclass, client, title windows[int(columns[2])] = int(columns[0], 16) if pid in windows: self.embedWindow(windows[pid]) # this is where the magic happens... self.external.finished.connect(self.close) elif self._tries < 100: self._tries += 1 self.timer.start() else: QMessageBox.warning(self, 'Error', 'Could not find WID for PID: %s' % pid) else: QMessageBox.warning(self, 'Error', 'Could not find PID for: %r' % self.external.program())if __name__ == '__main__': if len(sys.argv) > 1: if shutil.which(sys.argv[1]): app = QApplication(sys.argv) window = Window(sys.argv[1], sys.argv[2:]) window.setGeometry(100, 100, 800, 600) window.show() sys.exit(app.exec_()) else: print('could not find program: %r' % sys.argv[1]) else: print('usage: python %s <external-program-name> [args]' % os.path.basename(__file__)) 这篇关于如何检测嵌入QWidget.createWindowContainer的外部窗口何时关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-31 14:43