获取实际的 Qt window 标题

Get the actual Qt window title

我需要获得Qt顶层window(或MDI子window)的visible标题,因为我想列出window 不同位置的标题就像它们对用户可见一样。

考虑一个支持多个顶级编辑器 windows(或具有类似用途的 MDI 区域)的程序,该程序应列出那些 windows 的标题,例如菜单或内部“window 经理".

如果我想列出那些 windows 并且还支持 windowModified 属性 的 [*] 占位符,他们的 windowTitle() 将 return 这个烦人的占位符,不管他们的状态如何。

不幸的是,windowTitle 功能有点抽象,原因如下:

考虑到上述情况,有没有办法获得 Qt 为 window 设置的 真实 标题?

OS 将 最终 显示在顶级 window 的标题栏中的标题没有绝对和确定的方法。

windowTitle documentation, some systems might support displaying the applicationDisplayName 中所述。一些高度可定制的 (Linux) OS 可能会显示所提供标题的更改版本。几乎没有办法获得“最终”显示的标题,除非您想深入研究与 Window 管理器交互的特定 OS 模块(而且这可能还不够,因为在 *nix 系统上可以进行高水平的定制。

考虑到与 OP 相关的是“内部”window 标题(Qt 最终“中继”到系统的内容),解决方案是实现 Qt 实际上在内部使用 qt_setWindowTitle_helperHelper().

请注意,Qt 实现并不完美。当使用占位符字符串的特定组合时,会出现一些奇怪的情况。例如:

  • 使用 [*] [*] [*] 作为 window 标题会导致“[*]”显示为未修改的 window,否则显示“* [*] *”;
  • [*] [*][*] [*],未修改的window标题是“ [*] [*]”(注意前导space),另一个是“* [*]* [*]”。 =47=]

虽然,如上所述,Qt 实现远非完美,但我们感兴趣的是 实际 window 标题转发给 OS,所以我们必须坚持,因为视觉结果是重要的方面,无论它是否“正确”。

最后,请记住,如果 Qt 开发人员决定更改此行为(我相信他们应该更改),此实现将来可能会失效。

以下代码是一个简单的函数,它将 return 实际 window 标题转发给给定小部件的 OS,可用于必须显示 visible 标题的任何情况:

def realWindowTitle(widget):
    title = widget.windowTitle()
    placeHolder = '[*]'
    if not placeHolder in title:
        return title
    phSize = len(placeHolder)

    style = widget.style()
    if (widget.isWindowModified()
        and style.styleHint(
            style.SH_TitleBar_ModifyNotification, None, widget)
            # for PyQt6 or full Enum support use
            # style.StyleHint.SH_TitleBar_ModifyNotification
        ):
            replaceHolder = '*'
    else:
        replaceHolder = ''

    index = title.find(placeHolder)
    while index != -1:
        index += phSize
        count = 1

        while title.find(placeHolder, index) == index:
            count += 1
            index += phSize

        if count % 2: # odd number of [*] -> replace last one
            lastIndex = title.rfind(placeHolder, 0, index)
            title = (title[:lastIndex] 
                + replaceHolder 
                + title[lastIndex + phSize:])

        index = title.find(placeHolder, index)

    # return "escaped" sequences of the remaining double placeholders
    return title.replace('[*][*]', placeHolder)