仅通过对象名称在 QApplication 中查找项目

Find item in QApplication by only the objectname

我想通过 QApplication 中的对象名称字符串名称查找任何对象

类似

QApplication.instance().findByClassName("codeEditor")

这应该 return 具有这个类名的小部件列表,如果有多个小部件我可以迭代

[QPushButton (QPushButton at: 0x0000008EA3B3DD80), QWidget (QWidget at: 0x0000008EA3F33F40)]

我读过 this 但它需要一个对象,我想要 *

这是我想出的用于测试的东西:

def findWidget(name):
    name = name.lower()
    widgets = self.topLevelWidgets()
    widgets = widgets + self.allWidgets()
    ret = dict()
    c = 0
    for x in widgets:
        c += 1
        if name in x.objectName.lower() or name in str(x.__class__).lower():
            ret["class:"+str(x.__class__)+str(c)] = "obj:"+x.objectName;continue
        if hasattr(x, "text"):
            if name in x.text.lower():
                ret["class:"+str(x.__class__)+str(c)] = "obj:"+x.objectName
    return ret

它甚至没有找到明显存在的 'InfoFrame':

>>> widget("info")

{}

我想出了这个效果很好

def getWidgetByClassName(name):
    widgets = QApplication.instance().topLevelWidgets()
    widgets = widgets + QApplication.instance().allWidgets()
    for x in widgets:
        if name in str(x.__class__).replace("<class '","").replace("'>",""):
            return x
def getWidgetByObjectName(name):
    widgets = QApplication.instance().topLevelWidgets()
    widgets = widgets + QApplication.instance().allWidgets()
    for x in widgets:
        if str(x.objectName) == name:
            return x
def getObjects(name, cls=True):
    import gc
    objects = []
    for obj in gc.get_objects():
        if (isinstance(obj, PythonQt.private.QObject) and
            ((cls and obj.inherits(name)) or
             (not cls and obj.objectName() == name))):
            objects.append(obj)
    return objects

通常不可能找到所有 QObject 个实例。 Qt 不跟踪它们,因为对象可以在多个线程中使用,并且跟踪它们的开销会不必要地高。

Qt 确实会跟踪所有小部件,因为小部件只能存在于主线程中,而且它们是相当重的对象,因此跟踪它们的开销相对较小。

因此,您可以搜索从 QApp.allWidgets() 获得的所有小部件及其所有子项。您还可以查看您可以访问的对象的子对象。但是,如果给定的对象没有父对象,或者不属于某个小部件,那么您将无法通过这种方式找到它。

在 Python 中,可以使用 gc module 对任何 class 执行此操作。它提供了一种方法来检索垃圾收集器跟踪的所有对象的引用。这显然是一种非常低效的方法,但它确实(几乎)保证可以找到任何类型的对象。

这是一个通过 class-name 或 object-name 获取所有 QObject 实例列表的函数:

def getObjects(name, cls=True):
    objects = []
    for obj in gc.get_objects():
        if (isinstance(obj, QtCore.QObject) and
            ((cls and obj.inherits(name)) or
             (not cls and obj.objectName() == name))):
            objects.append(obj)
    return objects

不过,这只是一个真正的调试工具 - 对于大型应用程序,很容易有几十万个对象需要检查。

如果您只需要 QWidget 的子 class 对象,请使用此函数:

def getWidgets(name, cls=True):
    widgets = []
    for widget in QtGui.QApplication.allWidgets():
        if ((cls and widget.inherits(name)) or
            (not cls and widget.objectName() == name)):
            widgets.append(widget)
    return widgets

PS:

如果您想找到所有属于 QObject 的子class 对象,只有当您能以某种方式确保应用程序中的所有实例都有一个有效的父对象(根据定义,它也必须是 QObject)。有了它,您就可以使用 root_object.findChildren(QObject) 来获取完整列表。也可以使用 findChild or findChildren 通过对象名称搜索单个对象(如果需要,可以选择使用正则表达式)。