-->

Find item in QApplication by only the objectname

2020-03-01 02:33发布

问题:

i want to find any object by a objectname string name inside of the QApplication

Something like

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

which should return a list of widgets with this classname that i can iterate over if there is more then one

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

I have read this but it requires a object and i want something like *

This is something i came up with for testing:

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

It doesn't even find the 'InfoFrame' which is clearly there:

>>> widget("info")


{}

回答1:

I came up with this which works quite well

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


回答2:

In Python, this can be done for any class using the gc module. It provides a method for retrieving the references of all objects tracked by the garbage-collector. This is obviously a quite inefficient approach, but it does (almost) guarantee that any type of object can be found.

Here's a function to get a list of all QObject instances either by class-name or object-name:

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

This is only really a debugging tool, though - for a large application, there could easily be several hundred thousand objects to check.

If you only need objects which are subclasses of QWidget, use this function:

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:

If you want to find all objects which are subclasses of QObject, this can only be achieved if you can somehow ensure that all the instances in your application have a valid parent (which, by definition, must also be a QObject). With that in place, you can then use root_object.findChildren(QObject) to get the full list. It is also possible to use findChild or findChildren to search for individual objects by object-name (optionally using a regular-expression, if desirable).



回答3:

It is not possible to find all QObject instances in general. Qt does not keep track of them since objects can be used in multiple threads and the overhead of tracking them would be unnecessarily high.

Qt does keep track of all widgets, though, since widgets can only exist in the main thread, and they are fairly heavy objects so tracking them has comparably little overhead.

So, you could search all widgets you get from QApp.allWidgets(), and all of their children. You can also look through children of objects you otherwise have access to. But if a given object is parentless, or is not owned by a widget, then you won't find it that way.