问题
I am trying to take a native window from an other process and manage it as a docking widget in my process.
This is very similar to: How to manage separate GUI processes in a Qt application?
I have found the following which gets me pretty far: https://gist.github.com/torarnv/c5dfe2d2bc0c089910ce
Problem is the dock window size does not match the size of the contents it's wrapping (there is a margin which it about 15px wide and 40px tall (see pictures for examples)).
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import Qt
import logging
envent_type_lookup = {v:k for k,v in QtCore.QEvent.__dict__.items() if isinstance(v, int)}
class DockingWindowProxy(QtWidgets.QDockWidget):
def __init__(self, hwnd, *args, **kwargs):
super().__init__(*args, **kwargs)
self.window_wrapper = QtGui.QWindow.fromWinId(hwnd)
print('fromWinId window size', self.window_wrapper.size())
self.window_widget = QtWidgets.QWidget.createWindowContainer(self.window_wrapper)
self.setWindowTitle("Wrapper")
print('windowContainer widget size', self.window_widget.size())
self.setWidget(self.window_widget)
print('dock widget size', self.size())
self.installEventFilter(self)
def eventFilter(self, obj, ev):
print(f"{envent_type_lookup[ev.type()]} \t {self.window_wrapper.size()}, {self.window_widget.size()}")
return False
if __name__ == '__main__':
import win32gui
logging.basicConfig(level=logging.DEBUG)
app = QtWidgets.QApplication([])
sample = QtWidgets.QPushButton("Test")
sample.show()
print('Original window size', sample.size())
w = sample.window()
hwnd = w.winId().__int__()
pw = DockingWindowProxy(hwnd)
pw.show()
app.exec_()
Results:
Should look like:
Here are the console print outputs indicating the sizes each component has at various times:
Original window size PyQt5.QtCore.QSize(75, 23)
fromWinId window size PyQt5.QtCore.QSize(120, 23)
windowContainer widget size PyQt5.QtCore.QSize(640, 480)
dock widget size PyQt5.QtCore.QSize(640, 480)
PlatformSurface PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
WinIdChange PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
WindowIconChange PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
Polish PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
Move PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
Resize PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(200, 100)
Show PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
CursorChange PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ShowToParent PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
PolishRequest PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
LayoutRequest PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
UpdateLater PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
UpdateRequest PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
WindowActivate PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ActivationChange PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
InputMethodQuery PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ShortcutOverride PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
KeyPress PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
WindowDeactivate PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ActivationChange PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
回答1:
Looks like the key issue was to set the FramelessWindowHint windowFlag BEFORE showing the window whose hwnd will be used. Then everything appears to work as expected.
来源:https://stackoverflow.com/questions/60381894/embedding-native-windows-inside-qdockwidget