简体   繁体   English

获取实际的 Qt 窗口标题

[英]Get the actual Qt window title

I need to get the visible title of a Qt top level window (or MDI subwindow), because I want to list window titles in different places just like they're visible for the user.我需要获取 Qt 顶级窗口(或 MDI 子窗口)的可见标题,因为我想在不同的地方列出窗口标题,就像它们对用户可见一样。

Consider a program that supports multiple top level editor windows (or an MDI area with similar purposes) that should list the titles of those windows, like a menu or an internal "window manager".考虑一个支持多个顶级编辑器窗口(或具有类似目的的 MDI 区域)的程序,该程序应列出这些窗口的标题,如菜单或内部“窗口管理器”。

If I want to list those windows and also support the [*] placeholder for the windowModified property, their windowTitle() will return that annoying placeholder no matter of their state.如果我想列出这些窗口并且还支持windowModified属性的[*]占位符,那么无论它们的状态如何,它们的windowTitle()都会返回那个烦人的占位符。

Unfortunately, the windowTitle feature is a bit abstract, for the following reasons:不幸的是, windowTitle功能有点抽象,原因如下:

  • due to the windowModified feature, it always returns the placeholder if it's set;由于windowModified功能,如果设置了占位符,它总是返回;
  • the [*] placeholder can be "escaped" with multiple, even occurrences, in order to actually display [*] in the window title; [*]占位符可以多次甚至出现“转义”,以便在窗口标题中实际显示[*]
  • if the "actual" windowTitle property is an empty string (the default), it falls back to the windowFilePath property, which not only always has the [*] placeholder, but could also behave oddly in the rare case that property contains the [*] placeholder;如果“实际” windowTitle属性是一个空字符串(默认值),它会回windowFilePath属性,该属性不仅总是[*]占位符,而且在属性包含[*]占位符; while I realize that this is a very odd (and somehow irresponsible, assuming the system actually supports it) situation, I still want a reliable way to get the currently resulting window title, even in those rare (though "wrong") situations;虽然我意识到这是一个非常奇怪(并且在某种程度上不负责任,假设系统实际上支持它)的情况,但我仍然想要一种可靠的方法来获取当前生成的窗口标题,即使在那些罕见的(虽然“错误”)情况下也是如此;

Is there a way to get the real title that Qt sets for the window, considering the above?考虑到上述情况,有没有办法获得 Qt 为窗口设置的真实标题?

There is no absolute and certain way to get the title that the OS will finally show in the title bar of a top level window.没有绝对和确定的方法来获取操作系统最终将在顶级窗口的标题栏中显示的标题。

As explained in the windowTitle documentation, some systems might support displaying the applicationDisplayName .windowTitle文档中所述,某些系统可能支持显示applicationDisplayName Some highly customizable (Linux) OS might show an altered version of the provided title.一些高度可定制的 (Linux) 操作系统可能会显示所提供标题的更改版本。 There is almost no way to get the "final", displayed title, unless you want to dig into specific OS modules that interface with the Window Manager (and that might not be enough anyway, due to the high level of customization possible on *nix systems).几乎没有办法获得“最终”显示的标题,除非您想深入了解与窗口管理器交互的特定操作系统模块(这可能还不够,因为 *nix 上可能有高水平的定制系统)。

Considering that what's relevant for the OP is the "internal" window title (what Qt finally "relays" to the system), the solution is to implement what Qt actually does internally with qt_setWindowTitle_helperHelper() .考虑到与 OP 相关的是“内部”窗口标题(Qt 最终“中继”到系统),解决方案是使用qt_setWindowTitle_helperHelper()实现 Qt 在内部实际执行的操作。

Be aware that the Qt implementation is not perfect.请注意,Qt 实现并不完美。 There are some odd cases when specific combinations of the placeholder string are used.当使用占位符字符串的特定组合时,会出现一些奇怪的情况。 For instance:例如:

  • using [*] [*] [*] as window title results in " [*] " being shown for an unmodified window and " * [*] * " otherwise;使用[*] [*] [*]作为窗口标题会导致未修改的窗口显示“ [*] *] ”,否则显示“ * [*] * ”;
  • with [*] [*][*] [*] , the unmodified window title is " [*] [*] " (note the leading space) and the other is " * [*]* [*] "使用[*] [*][*] [*] ,未修改的窗口标题为“ [*] [*] ”(注意前导空格),另一个为“ * [*]* [*]

While, as said above, the Qt implementation is far from perfect, what we're interested into is the actual window title relayed to the OS, so we must adhere to it, since the visual result is the important aspect, no matter whether it's "correct" or not.虽然如上所述,Qt 实现远非完美,但我们感兴趣的是实际的窗口标题传递给操作系统,所以我们必须坚持它,因为视觉结果是重要的方面,不管它是否“正确”与否。

Finally, remember that this implementation might become invalid in the future, in case Qt developers decide to change this behavior (and, I believe, they should).最后,请记住,如果 Qt 开发人员决定改变这种行为(我相信他们应该),这种实现将来可能会变得无效。

The following code is a simple function that will return the actual window title relayed to the OS for a give widget, which can be used for any situation in which the visible title has to be displayed:以下代码是一个简单的函数,它将返回实际窗口标题,该窗口标题为给定的小部件传递给操作系统,可用于必须显示可见标题的任何情况:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM