仅通过对象名在 QApplication 中查找项目
Posted
技术标签:
【中文标题】仅通过对象名在 QApplication 中查找项目【英文标题】:Find item in QApplication by only the objectname 【发布时间】:2016-12-07 07:03:49 【问题描述】:我想通过 QApplication 中的 objectname 字符串名称查找任何对象
类似
QApplication.instance().findByClassName("codeEditor")
它应该返回一个具有这个类名的小部件列表,如果有多个,我可以对其进行迭代
[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")
【问题讨论】:
因为(几乎)一切都源自QObject
寻找该类类型
@SebastianLange 你是什么意思?
@SebastianLange snag.gy/md8M7Y.jpg
【参考方案1】:
我想出了这个效果很好
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
【讨论】:
allWidgets
必然包括topLevelWidgets
。使用其中之一,而不是两者。
这些功能都不起作用。对于第一个,str(x.__class__)
将返回类似"<class 'PyQt4.QtGui.QWidget'>"
的东西,所以它显然永远不会匹配。您需要使用x.__class__.__name__
,但即便如此,它也不会匹配子类。对于第二个函数,你需要使用str(x.objectName())
,否则它永远不会匹配任何东西。请注意,这两个函数都只会返回找到的第一个对象,而不是所有匹配对象的列表(这是问题所要求的)。
您所做的更改并不能解决任何问题。【参考方案2】:
在 Python 中,可以使用 gc module 对任何类完成此操作。它提供了一种方法来检索垃圾收集器跟踪的所有对象的引用。这显然是一种效率很低的方法,但它确实(几乎)保证可以找到任何类型的对象。
这是一个函数,可以通过类名或对象名获取所有 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
的子类对象,请使用此函数:
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
的子类的所有对象,只有在您能够以某种方式确保应用程序中的所有实例都有一个有效的父类(根据定义,它也必须是一个@ 987654330@)。有了它,您就可以使用root_object.findChildren(QObject)
获取完整列表。也可以使用 findChild 或 findChildren 按对象名称搜索单个对象(如果需要,可以选择使用正则表达式)。
【讨论】:
这是一个好方法,但对我不起作用:i.imgur.com/HreomDd.png @Bluscream。如果您不创建任何QObject
实例,您为什么希望它能够工作?您显然必须在创建对象的同一 python 解释器中运行它。
但我想搜索现有对象,而不是我创建的对象,显然......
@Bluscream。 谁创建它们没有区别。这些对象要么存在于当前的 python 解释器会话中,要么不存在。如果您想确切知道当前存在哪些对象,只需执行import gc; for x in gc.get_objects(): print(repr(x))
(警告:这可能是一个很长的列表)。
@Bluscream。这一切对我来说都很好。我猜您的应用程序一定有问题,或者您使用的某个第三方库可能有问题。【参考方案3】:
通常不可能找到所有QObject
实例。 Qt 不跟踪它们,因为对象可以在多个线程中使用,并且跟踪它们的开销会不必要地高。
不过,Qt 确实会跟踪所有小部件,因为小部件只能存在于主线程中,而且它们是相当重的对象,因此跟踪它们的开销相对较小。
因此,您可以搜索从QApp.allWidgets()
获得的所有小部件及其所有子部件。您还可以查看您可以访问的对象的子对象。但是,如果给定的对象是无父对象,或者不属于某个小部件,那么您将不会以这种方式找到它。
【讨论】:
我想到了一些选择器,比如如果你想在 jquery 中搜索 dom$('someElement')
@Bluscream 是的。所以?我想到了各种各样的事情。您对此答案有疑问或评论吗?说你想到了一些随机的东西并没有帮助。
如果您认为需要全局对象搜索,那您就错了。跟踪您需要的对象:您拥有做好工作的最佳资源。该框架会帮助你,但它不会为你做这件事,因为它的设计无法预见你的情况。
我没做错,javascript 也有全局 ui 搜索,这是每个人都经常使用的东西。
@Bluscream Qt 也有。对于 Ui 对象 - 即 QWidget
s。这就是您所能拥有的一切,因为只有小部件存在于一个线程上,因此搜索所有小部件是有意义的。从那个线程。以上是关于仅通过对象名在 QApplication 中查找项目的主要内容,如果未能解决你的问题,请参考以下文章