On RPi OS (Bookworm) as of 2025. Configured with raspi-config
to boot into a terminal rather than the desktop.
Trying to run PyQt6 application on the bare minimum software stack. This is the application, hello.py
:
#!/usr/bin/env python3
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout
class HelloWorldApp(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle("Hello, World!")
layout = QVBoxLayout()
label = QLabel("Hello, World!")
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(label)
self.setLayout(layout)
def main():
app = QApplication(sys.argv)
window = HelloWorldApp()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
linuxfb and eglfs yay, wayland not so much. Any help appreciated.
QT_QPA_PLATFORM=linuxfb python3 hello.py
works and is practically INSTANT. Yay!
cat << EOF > eglfs.json
{
"device": "/dev/dri/card1",
"outputs": [
{
"name": "HDMI1",
"mode": "1920x1080"
}
]
}
EOF
QT_QPA_EGLFS_KMS_CONFIG=eglfs.json QT_QPA_PLATFORM=eglfs python3 hello.py
also works.
But neither has window decorations. Qt no longer has QWT which used to have a windowing system.
So we nowadays probably need to use Wayland.
And here the trouble begins. Every time I touch anything Wayland, it's usually an undocumented broken mess that never "just works".
But here we go...
labwc # Need to run this command on physical terminal, not over ssh?
WAYLAND_DISPLAY=wayland-0 QTQT_QPA_PLATFORM=wayland python3 hello.py
$ WAYLAND_DISPLAY=wayland-0 QTQT_QPA_PLATFORM=wayland python3 hello.py
QStandardPaths: wrong permissions on runtime directory /run/user/1000, 0770 instead of 0700
qt.qpa.wayland: Loading shell integration failed.
qt.qpa.wayland: Attempted to load the following shells QList("xdg-shell", "wl-shell", "ivi-shell")
wayfire # Need to run this command on physical terminal, not over ssh?
Has some warnings about "seatd" - probably yet another something complicated from Red Hat?
$ QT_WAYLAND_SHELL_INTEGRATION=xdg-shell WAYLAND_DISPLAY=wayland-1 QTQT_QPA_PLATFORM=wayland python3 hello.py
QStandardPaths: wrong permissions on runtime directory /run/user/1000, 0770 instead of 0700
qt.qpa.wayland: Loading shell integration failed.
qt.qpa.wayland: Attempted to load the following shells QList("xdg-shell")
qt6/plugins/wayland-shell-integration/libqt-shell.so seems to be a Qt specidic "shell" other than XDG which may be more liberal and support move(). So can we use it?
sudo apt install -y qt6-wayland-dev qml6-module-qtwayland-compositor qml6-module-qtqml
# qtwayland5-examples exists, but no qt6 version?
git clone https://github.com/qt/qtwayland/
cd qtwayland
git checkout 6.4.2
cd examples/wayland/qtshell/
cmake .
make -j4
cat << EOF > eglfs.json
{
"device": "/dev/dri/card1",
"outputs": [
{
"name": "HDMI1",
"mode": "1920x1080"
}
]
}
EOF
QT_DEBUG_PLUGINS=1 QT_WAYLAND_SHELL_INTEGRATION=qt-shell QT_QPA_EGLFS_KMS_CONFIG=eglfs.json QT_QPA_PLATFORM=eglfs ./qtshell
QQmlApplicationEngine failed to load component
qrc:/qml/main.qml:11:5: Type CompositorScreen unavailable
qrc:/qml/CompositorScreen.qml:55:21: Type Chrome unavailable
qrc:/qml/Chrome.qml:180:9: Cannot assign to non-existent property "staysOnTop"
When we comment out these two lines
//staysOnBottom: shellSurface.windowFlags & Qt.WindowStaysOnBottomHint
//staysOnTop: !staysOnBottom && shellSurface.windowFlags & Qt.WindowStaysOnTopHint
in `qml/Chrome.qml` and recompile, we get a desktop background!
QT_DEBUG_PLUGINS=1 QT_WAYLAND_SHELL_INTEGRATION=qt-shell QT_QPA_EGLFS_KMS_CONFIG=eglfs.json QT_QPA_PLATFORM=eglfs ./qtshell
error in client communication (pid 731)
error in client communication (pid 731)
error in client communication (pid 731)
...
In another terminal:
QT_DEBUG_PLUGINS=1 QT_WAYLAND_SHELL_INTEGRATION=qt-shell WAYLAND_DISPLAY=wayland-0 QT_QPA_PLATFORM=wayland python hello.py
QStandardPaths: wrong permissions on runtime directory /run/user/1000, 0770 instead of 0700
qt.qpa.wayland: Loading shell integration failed.
qt.qpa.wayland: Attempted to load the following shells QList("qt-shell")
Does not run...
QT_DEBUG_PLUGINS=1 QT_WAYLAND_SHELL_INTEGRATION=qt-shell WAYLAND_DISPLAY=wayland-0 QT_QPA_PLATFORM=wayland-egl python hello.py
qt.core.plugin.factoryloader: checking directory path "/usr/bin/platforms" ...
qt.core.library: "/usr/lib/aarch64-linux-gnu/qt6/plugins/platforms/libqwayland-egl.so" cannot load: Cannot load library /usr/lib/aarch64-linux-gnu/qt6/plugins/platforms/libqwayland-egl.so: (/usr/lib/aarch64-linux-gnu/qt6/plugins/platforms/libqwayland-egl.so: undefined symbol: _ZNK15QtWaylandClient19QWaylandIntegration22queryKeyboardModifiersEv)
qt.core.plugin.loader: QLibraryPrivate::loadPlugin failed on "/usr/lib/aarch64-linux-gnu/qt6/plugins/platforms/libqwayland-egl.so" : "Cannot load library /usr/lib/aarch64-linux-gnu/qt6/plugins/platforms/libqwayland-egl.so: (/usr/lib/aarch64-linux-gnu/qt6/plugins/platforms/libqwayland-egl.so: undefined symbol: _ZNK15QtWaylandClient19QWaylandIntegration22queryKeyboardModifiersEv)"
qt.qpa.plugin: Could not load the Qt platform plugin "wayland-egl" 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: xcb, wayland-egl, eglfs, linuxfb, minimalegl, wayland, minimal, offscreen, vkkhrdisplay, vnc.
Aborted
labwc -s "python3 hello.py"
?