I am currently learning the PyQt6 library and I want to get the geometry of the window. The issue is that the x and y positions are always 0 even after I changed the position of the window on the screen.
- OS: Ubuntu
- Python version: 3.9
import sys
from PyQt6.QtWidgets import QApplication, QVBoxLayout, QPushButton, QWidget
from PyQt6.QtCore import QTimer
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 300)
self.setWindowTitle("Main Window")
layout = QVBoxLayout()
btn = QPushButton("Click", self)
btn.clicked.connect(self.print_geometry)
layout.addWidget(btn)
self.setLayout(layout)
self.show()
def print_geometry(self):
print(self.geometry()) # This will now print the correct geometry
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec())
Output:
PyQt6.QtCore.QRect(0, 0, 200, 300)
PyQt6.QtCore.QRect(0, 0, 200, 300)
PyQt6.QtCore.QRect(0, 0, 200, 300)
PyQt6.QtCore.QRect(0, 0, 200, 300)
I don't know why it is returning 0 for x and y positions. It should have returned the exact position.
I am currently learning the PyQt6 library and I want to get the geometry of the window. The issue is that the x and y positions are always 0 even after I changed the position of the window on the screen.
- OS: Ubuntu
- Python version: 3.9
import sys
from PyQt6.QtWidgets import QApplication, QVBoxLayout, QPushButton, QWidget
from PyQt6.QtCore import QTimer
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 300)
self.setWindowTitle("Main Window")
layout = QVBoxLayout()
btn = QPushButton("Click", self)
btn.clicked.connect(self.print_geometry)
layout.addWidget(btn)
self.setLayout(layout)
self.show()
def print_geometry(self):
print(self.geometry()) # This will now print the correct geometry
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec())
Output:
PyQt6.QtCore.QRect(0, 0, 200, 300)
PyQt6.QtCore.QRect(0, 0, 200, 300)
PyQt6.QtCore.QRect(0, 0, 200, 300)
PyQt6.QtCore.QRect(0, 0, 200, 300)
I don't know why it is returning 0 for x and y positions. It should have returned the exact position.
Share Improve this question edited Feb 1 at 20:40 ZCGCoder 5322 gold badges10 silver badges29 bronze badges asked Jan 30 at 15:58 Rakesh B SirviRakesh B Sirvi 581 silver badge6 bronze badges 6 | Show 1 more comment1 Answer
Reset to default 2why it doesn't work
On Ubuntu, Wayland is used by default for regular user sessions. Wayland has certain limitations, including restricting access to low-level details like window position, which caused this issue. However, sudo runs the program with root privileges, which forces the system to use X11 (instead of Wayland), where such restrictions don't apply. This is why running the program with sudo sometimes works, but it isn't the best solution.
Solution Methods:
The issue was resolved by setting the QT_QPA_PLATFORM environment variable to xcb in the script, which forces PyQt6 to use X11 instead of Wayland. This allowed the window geometry to be fetched correctly without requiring root privileges. Additionally, installing the X11 plugins (libxcb-cursor0, libxcb1, and libxcb-xinerama0) ensures that X11 works properly
Method 1: Running the app as sudo:
If you run the application with sudo, it will use X11 instead of Wayland. This bypasses the restrictions imposed by Wayland and allows window geometry to be fetched correctly. However, running GUI applications as root is generally not recommended due to potential security and permission issues.
Method 2: Set the environment variable to force Qt to use xcb:
A cleaner solution is to explicitly set the QT_QPA_PLATFORM
environment variable to xcb in the Python script, forcing Qt to use the X11 plugin. This avoids the need to run the application as root and resolves the geometry issue without requiring elevated privileges:
import os
os.environ['QT_QPA_PLATFORM'] = 'xcb'
The error you might encounter
qt.qpa.plugin: From 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: wayland, vnc, linuxfb, xcb, eglfs, vkkhrdisplay, minimalegl, minimal, offscreen, wayland-egl.
Aborted (core dumped)
Solution: If you wish to use X11 through sudo, you must install the necessary plugins to support it. You can install the required X11 plugins with the following commands:
sudo apt-get install libxcb-cursor0 libxcb1 libxcb-xinerama0
These libraries are needed for the X11 plugin to function properly and allow you to retrieve window geometry correctly
final code
import sys
import os
from PyQt6.QtWidgets import QApplication, QVBoxLayout, QPushButton, QWidget
os.environ['QT_QPA_PLATFORM'] = 'xcb'
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(200, 300)
self.setWindowTitle("Main Window")
layout = QVBoxLayout()
btn = QPushButton("Click", self)
btn.clicked.connect(self.print_geometry)
layout.addWidget(btn)
self.setLayout(layout)
self.show()
def print_geometry(self):
print("Widget Geometry:", self.geometry())
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
sys.exit(app.exec())
- Official Wayland Documentation
- X.Org (X11) Documentation
- A Comparison of X11 and Wayland
- Ubuntu Blog on Wayland vs X11
- Qt Platform Abstraction (QPA) Overview
- Qt Wayland Platform Plugin
- Qt XCB (X11) Platform Plugin
geometry
property docs link to a relevant page: "On Wayland, programmatically setting or getting the position of a top-level window from the client-side is typically not supported. [...] when queried, the window position will always be returned as QPoint(0, 0)." – musicamante Commented Jan 30 at 22:49