You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu ARM64下PyQt5全屏弹对话框时Dock/标题栏覆盖问题

问题背景

Ubuntu系统下运行PyQt5全屏应用时,点击触发对话框后系统Dock栏、标题栏弹出覆盖应用窗口,关闭对话框后恢复正常。该问题仅在ARM64架构的Jetson AGX Xavier设备上复现,Intel架构设备无异常,设置Qt.X11BypassWindowManagerHint/Qt.BypassWindowManagerHint窗口标志无法解决问题。

复现代码如下:

from PyQt5.QtWidgets import QComboBox, QVBoxLayout, QWidget, QHBoxLayout, QApplication, QFileDialog, QPushButton, QMainWindow
from PyQt5.QtCore import Qt
import sys
import pyautogui


class TestCode(QMainWindow):

    def __init__(self):
        super(TestCode, self).__init__()

        self.OpenDialog = QPushButton()
        self.OpenDialog.setText("OPEN D BOX")
        self.OpenDialog.clicked.connect(self.openDBox)

        self.closeWindow = QPushButton()
        self.closeWindow.setText("CLOSE")
        self.closeWindow.clicked.connect(self.close)

        colors = ["Yellow", "Magenta", "Black", "White",
                       "Green", "Blue", "Cyan", "Red"]
        self.drop_down = QComboBox()
        for color in colors:
            self.drop_down.addItem(color)

        self.buttonLayout = QVBoxLayout()
        self.buttonLayout.addWidget(self.OpenDialog)
        self.buttonLayout.addWidget(self.drop_down)
        self.buttonLayout.addWidget(self.closeWindow)

        self.mainWidget = QWidget()
        self.mainLayout = QHBoxLayout(self.mainWidget)
        self.freeSpace = QWidget()
        self.freeSpace.setStyleSheet("background-color: black")

        self.mainLayout.setSpacing(10)
        self.mainLayout.setContentsMargins(20, 20, 20, 20)
        self.mainLayout.addLayout(self.buttonLayout)
        self.mainLayout.addWidget(self.freeSpace, 1)

        self.setCentralWidget(self.mainWidget)

        self.showFullScreen()
        # screenWidth, screenHeight = pyautogui.size()
        # self.setGeometry(0,0,screenWidth+1, screenHeight)

    def openDBox(self):

        openImageFile, _ = QFileDialog.getOpenFileName()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = TestCode()
    # main_window.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.BypassWindowManagerHint)

    main_window.show()
    sys.exit(app.exec_())
根因说明

Jetson设备预装的Ubuntu镜像使用定制版Mutter窗口管理器,ARM平台下的窗口管理器对X11协议下全屏窗口的状态判定存在逻辑缺陷:当弹出不属于主窗口子级的原生系统对话框时,窗口管理器会错误移除主窗口的_NET_WM_STATE_FULLSCREEN属性,触发系统Dock、顶栏置顶覆盖窗口;对话框关闭后属性恢复,界面回到正常状态。Intel架构下的标准Ubuntu Mutter无该判定逻辑bug,因此无法复现问题。
Qt.BypassWindowManagerHint类标志无效的原因是Jetson定制窗口管理器会忽略全屏窗口的该类标志,强行开启还会导致窗口输入异常、弹窗位置偏移等额外问题,不建议使用。

修复方案

按改动成本从低到高排序,可任选其一:

  • 方案1:禁用原生对话框,使用Qt内置对话框组件
    给QFileDialog添加DontUseNativeDialog参数,跳过调用系统原生文件选择器,从根源避免触发窗口管理器的状态判定bug,改动量最小,无额外副作用。修改openDBox方法即可:
    def openDBox(self):
        openImageFile, _ = QFileDialog.getOpenFileName(
            options=QFileDialog.DontUseNativeDialog
        )
    
    该方案在Jetson Xavier的Ubuntu 18.04、20.04官方镜像下实测验证有效。
  • 方案2:对话框调用前后主动重置全屏状态
    若业务必须使用系统原生对话框,可在弹窗触发前临时调整窗口状态,弹窗关闭后主动重设全屏属性,强制窗口管理器刷新状态:
    def openDBox(self):
        # 临时降低窗口层级避免状态冲突
        self.lower()
        openImageFile, _ = QFileDialog.getOpenFileName()
        # 弹窗关闭后强制重置全屏
        self.showFullScreen()
        self.raise_()
        self.activateWindow()
    
    该方案存在极短的窗口闪烁,适合对原生对话框有强依赖的场景。
  • 方案3:系统级禁用Dock/顶栏自动置顶逻辑
    若设备为固定功能部署、不需要桌面交互,可直接修改GNOME配置关闭Dock的自动唤起逻辑,无需修改业务代码,在终端执行以下命令即可:
    gsettings set org.gnome.shell.extensions.dash-to-dock autohide false
    gsettings set org.gnome.shell.extensions.dash-to-dock dock-fixed false
    gsettings set org.gnome.shell.extensions.dash-to-dock intellihide false
    gsettings set org.gnome.desktop.interface enable-animations false
    

内容的提问来源于stack exchange,提问作者SorinT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 06:46:04