2

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")


{}

enter image description here

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Bluscream
  • 255
  • 1
  • 3
  • 18

3 Answers3

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
Bluscream
  • 255
  • 1
  • 3
  • 18
  • `allWidgets` necessarily includes `topLevelWidgets`. Use one or the other, not both. – Kuba hasn't forgotten Monica Dec 07 '16 at 17:55
  • 1
    Neither of these functions work. For the first one, `str(x.__class__)` will return something like `""`, so it's obviously never going to match. You need to use `x.__class__.__name__`, but even then, this won't match subclasses. For the second function, you need to use `str(x.objectName())`, otherwise it will never match anything. And note that both functions will only return the first object found, not a list of all matching objects (which is what the question asks for). – ekhumoro Dec 07 '16 at 19:34
  • The changes you made do not fix any of the problems. – ekhumoro Dec 08 '16 at 16:54
1

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).

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • This is a good approach but it doesn't work for me: http://i.imgur.com/HreomDd.png – Bluscream Dec 08 '16 at 08:35
  • @Bluscream. Why would you expect it to work if you don't create any `QObject` instances? You obviously have to run it in the same python interpreter where the objects were created. – ekhumoro Dec 08 '16 at 16:40
  • But i want to search for existing objects, not the ones i've created, obviously... – Bluscream Dec 08 '16 at 22:48
  • @Bluscream. It makes no difference **who** created them. The objects either exist in the current python interpreter session, or they don't. If you want to know exactly which objects currently exist, just do `import gc; for x in gc.get_objects(): print(repr(x))` (warning: it could be a very long list). – ekhumoro Dec 09 '16 at 00:01
  • This crashes the application >. – Bluscream Dec 09 '16 at 02:56
  • @Bluscream. No, it's you that did that. I'm guessing you just copy-pasted it as one line, instead of putting `import gc` on it's own line. Please try to use a little bit of common sense. – ekhumoro Dec 09 '16 at 03:31
  • I tried both and they are both causing the app to crash – Bluscream Dec 09 '16 at 03:32
  • 1
    @Bluscream. It all works perfectly fine for me. I guess your application must be buggy somehow, or perhaps some third party library you are using is buggy. – ekhumoro Dec 09 '16 at 03:41
  • i think its because i only have 2gb ram – Bluscream Dec 09 '16 at 03:42
  • @Bluscream. I very much doubt that. Are you running this in an IDE of some kind? If so, that could cause problems. Create a very simple pyqt test script that just creates a few widgets, and try the two functions in my answer to check that they work okay. If they don't, you know it's a problem with the IDE. – ekhumoro Dec 09 '16 at 03:50
  • @Bluscream. So you're using the pyTSon plugin, which I presume uses some kind of embedded python interpreter. I had a quick look at the forum, and the first thing I see is this: "**CAUTION** This is currently alpha software, so it can (and I guess, it will!) crash your client". Need I say more? – ekhumoro Dec 09 '16 at 04:08
  • everything may crash teamspeak. It doesn't have any error handling – Bluscream Dec 09 '16 at 04:09
  • @Bluscream. I really think you should have made it clearer this was specifically about a third-party application in your question. I've tagged it with `teamspeak` now. I have to say I'm a bit peeved that I've wasted a lot of my time trying to help you with this. – ekhumoro Dec 09 '16 at 04:27
  • its qt and python, why do you think your time was wasted? – Bluscream Dec 09 '16 at 04:28
0

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.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I thought of some selector like if you want to search the dom in jquery `$('someElement')` – Bluscream Dec 08 '16 at 09:37
  • @Bluscream Yes. So? I thought of all sorts of things. Do you have a question, or a comment on this answer? Saying that you thought of something random doesn't help. – Kuba hasn't forgotten Monica Dec 08 '16 at 14:18
  • If you think you need a global object search, you're doing it wrong. Keep track of the objects you need: you have the best resources to do a good job. The framework will help you, but it won't do it for you since its design can't foresee your circumstances. – Kuba hasn't forgotten Monica Dec 08 '16 at 14:19
  • I'm doing nothing wrong, javascript has a global ui search, too which is something everyone uses quite often. – Bluscream Dec 08 '16 at 22:50
  • @Bluscream Qt has it too. For the Ui objects - i.e. `QWidget`s. And that's all that you can have, because only widgets live on one thread so searching all of them makes sense. From that thread. – Kuba hasn't forgotten Monica Dec 08 '16 at 22:56