Get incorrect widget size by window handle
-
Test code:
#!/usr/bin/python3 import sys from PySide6 import QtCore from PySide6.QtWidgets import * from PySide6.QtGui import * from PySide6.QtCore import * class Example(QWidget): def __init__(self): super(Example, self).__init__() self.initUI() def initUI(self): self.setWindowFlags(Qt.FramelessWindowHint) self.setGeometry(300, 100, 300, 200) print(self.size()) if __name__ == '__main__': app = QApplication(sys.argv) window = Example() window.show() sys.exit(app.exec_())
This problem only happen on PySide6 and PyQt6, there is no problem on PyQt5 and PySide2. So I think it's qt6's problem.
-
Hi,
without seeing any relevant code, this answer is based on two assumptions:
- the window system is Wayland (because
xwininfo
is used) - by "window handle", you mean
QWidget::windowHandle()
(notQWindow::handle()
, which returns aQPlatformWindow *
)
FramlessWindowHint
produces a borderless window, if supported by the window manager. There's no guarantee, however.QWindow::geometry()
returns the window geometry exclusive of its frame (both in Qt 5 and Qt 6). The handling of window decorations has changed in the Qt Wayland implementation from Qt 5 to Qt 6. Without having any information about the Wayland configuration at hand, I can only suspect that a native window decoration is rendered regardless of theFramelessWindowHint
. Probably because it would not be possible to close/resize the window otherwise. The difference of 13/8 pixels represents the window decoration.
You can figure that out by callingQPlatformWindow::frameMargins()
.Cheers
Axel - the window system is Wayland (because
-
Thanks for your reply.
I think I should give you a specific example.import os import sys from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox from PySide6.QtWidgets import ( QApplication, QMainWindow ) from OCC.Display.backend import load_backend load_backend("qt-pyside6") import OCC.Display.qtDisplay as qtDisplay class App(QMainWindow): def __init__(self): super().__init__() self.title = "PyQt5 / pythonOCC" self.left = 300 self.top = 300 self.width = 800 self.height = 300 self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.canvas = qtDisplay.qtViewer3d(self) self.setCentralWidget(self.canvas) self.canvas.InitDriver() self.display = self.canvas._display a_box = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape() self.ais_box = self.display.DisplayShape(a_box)[0] self.display.FitAll() self.show() self.canvas.InitDriver() print(self.size()) if __name__ == "__main__": app = QApplication(sys.argv) ex = App() sys.exit(app.exec_())
(If you want to try this example, please install
pythonocc-core
conda install pythonocc-core
)
PythonOCC depends on window handle to display in qt window.
It causes so issues. -
@Tim-Tu
What's is returned byyourWidget->windowHandle()->handle()->frameMargins()
? -
@Axel-Spoerl said in Get incorrect widget size by window handle:
What's is returned by yourWidget->windowHandle()->handle()->frameMargins()?
There is some thing wrong:
print(self.windowHandle().Handle()) AttributeError: 'PySide6.QtGui.QWindow' object has no attribute 'Handle'
Did you means
contentsMargins
?
I have changed the test code:##Author github user @Tanneguydv, 2021 import os import sys from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox from PySide6.QtWidgets import ( QApplication, QWidget, QVBoxLayout ) from OCC.Display.backend import load_backend load_backend("qt-pyside6") import OCC.Display.qtDisplay as qtDisplay class App(QWidget): def __init__(self): super().__init__() self.title = "PyQt5 / pythonOCC" self.left = 300 self.top = 300 self.width = 800 self.height = 300 self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.lay = QVBoxLayout() self.setLayout(self.lay) self.canvas = qtDisplay.qtViewer3d(self) self.lay.addWidget(self.canvas) self.canvas.InitDriver() self.display = self.canvas._display a_box = BRepPrimAPI_MakeBox(10.0, 20.0, 30.0).Shape() self.ais_box = self.display.DisplayShape(a_box)[0] self.display.FitAll() self.show() self.canvas.InitDriver() print(self.size()) print(self.canvas.size()) print(self.contentsMargins()) print(self.canvas.contentsMargins()) if __name__ == "__main__": app = QApplication(sys.argv) ex = App() sys.exit(app.exec_())
The result:
Xw_Window created. Display3d class successfully initialized. ######################################### OpenGl information: GLvendor: AMD GLdevice: AMD Radeon Graphics (rembrandt, LLVM 15.0.7, DRM 3.52, 6.4.8-arch1-1) GLversion: 4.6 (Compatibility Profile) Mesa 23.1.5 GLSLversion: 4.60 Max texture size: 16384 Max FBO dump size: 16384x16384 Max combined texture units: 192 Max MSAA samples: 8 Viewport: 810x290 Window buffer: RGB8 ALPHA8 DEPTH24 STENCIL8 ResolutionRatio: 1 FBO buffer: GL_SRGB8_ALPHA8 GL_DEPTH24_STENCIL8 PySide6.QtCore.QSize(800, 300) PySide6.QtCore.QSize(778, 278) <PySide6.QtCore.QMargins(0, 0, 0, 0) at 0x7f5581c95ec0> <PySide6.QtCore.QMargins(0, 0, 0, 0) at 0x7f5581c95ec0>
-
There is some thing wrong:
print(self.windowHandle().Handle())
AttributeError: 'PySide6.QtGui.QWindow' object has no attribute 'Handle'handle()
, notHandle()
. -
@Axel-Spoerl
Sorry, but there still has no attributeprint(self.windowHandle().handle()) AttributeError: 'PySide6.QtGui.QWindow' object has no attribute 'handle'
-
@Axel-Spoerl
QWindow Class shows no sign of a (public at least, from C++, let alone Python)handle()
method? -
@JonB
Hm, qwindow.cpp:2050-2070:/*! Returns the platform window corresponding to the window. \internal */ QPlatformWindow *QWindow::handle() const { Q_D(const QWindow); return d->platformWindow; }
But...wait: It's a public method, documented as internal. That's why it doesn't show up in the documentation and maybe also not in python.
-
@Axel-Spoerl
:) And is itpublic
? If so, either it's not documented, or maybe because of that it didn't get added into PySide/PyQt (since the OP shows it not working from Python)? The comment shows\internal
....And it returns a
QPlatformWindow
, which does not seem to be documented either, so maybe that's why it's not provided?? [It seems to have been mentioned in Qt 4.8 but not since then? :) ] -
@JonB
Messages crossed ;-)
It's indeedpublic
.
QPlatformWindow
also isn't documented and probably not available in PySide/PyQt.
Thanks, Jon, for the hint. -
@Axel-Spoerl said in Get incorrect widget size by window handle:
It's indeed
public
.I just added to my previous: The comment shows
\internal
.... -
Nontheless, to conclude this thread somehow:
FramlessWindowHint
is a hint and doesn't guarantee that window is really rendered frameless.
Native handles seem to get rendered in the case at hand. The pixel difference represents their size.
Given that my proposed way to confirm it doesn't work out in Python, looking at the physical window on the screen is the only way to confirm.