Я работал над некоторой инфраструктурой отладки/тестирования для моего проекта на основе PyQt. Я отмечаю большинство виджетов со специальными атрибутами отладки, даже если виджеты были созданы на стороне C++.pyqt: Как получить последовательный доступ к кнопкам в QFileDialog
Однако множественные обращения к одной и той же кнопке в QFileDialog
, похоже, приводят к новым экземплярам обертки. То есть, если я получаю доступ к кнопке «Отмена» более одного раза, PyQt не возвращает один и тот же объект Python каждый раз.
Вот минимальная тестовая программа вы можете использовать, чтобы воспроизвести проблему:
from PyQt4.QtCore import QTimer
from PyQt4.QtGui import QApplication, QFileDialog, QDialogButtonBox
def print_debug_stuff():
# Find the dialog from among the top-level widgets
dlg = filter(lambda w: isinstance(w, QFileDialog), QApplication.topLevelWidgets())[0]
# Find the button box in the dialog, then find the cancel button
buttonBox = dlg.findChild(QDialogButtonBox, "buttonBox")
cancelButton = buttonBox.children()[2]
# Does it have our debug attribute? Can we add it?
print "Tagging button: '{}' ({})".format(cancelButton.text(), cancelButton)
print "...had my_debug_tag?", hasattr(cancelButton, "my_debug_tag")
# Add the debug attribute
buttonBox.children()[2].my_debug_tag = "hello"
print "...has my_debug_tag?", hasattr(cancelButton, "my_debug_tag")
app = QApplication([])
# Repeatedly print debug info until the program quits
timer = QTimer(timeout=print_debug_stuff)
timer.setInterval(100.0)
timer.start()
# Open a (non-native!) file save dialog
QFileDialog.getSaveFileName(options=QFileDialog.DontUseNativeDialog)
Я бы ожидать это запрограммировать для вывода чего-то вроде этого:
Tagging button: 'Cancel' (<PyQt4.QtGui.QPushButton object at 0x1013c8cb0>)
...had my_debug_tag? False
...has my_debug_tag? True
Tagging button: 'Cancel' (<PyQt4.QtGui.QPushButton object at 0x1013c8cb0>)
...had my_debug_tag? True
...has my_debug_tag? True
Tagging button: 'Cancel' (<PyQt4.QtGui.QPushButton object at 0x1013c8cb0>)
...had my_debug_tag? True
...has my_debug_tag? True
... но вместо этого , вот что я на самом деле вижу. Обратите внимание, что cancelButton
объект имеет различный адрес каждый раз, и атрибут отладки Я добавил утрачивается:
Tagging button: 'Cancel' (<PyQt4.QtGui.QPushButton object at 0x1013c8cb0>)
...had my_debug_tag? False
...has my_debug_tag? True
Tagging button: 'Cancel' (<PyQt4.QtGui.QPushButton object at 0x1013c8ef0>)
...had my_debug_tag? False
...has my_debug_tag? True
Tagging button: 'Cancel' (<PyQt4.QtGui.QPushButton object at 0x1013c8e60>)
...had my_debug_tag? False
...has my_debug_tag? True
Tagging button: 'Cancel' (<PyQt4.QtGui.QPushButton object at 0x1013c8dd0>)
...had my_debug_tag? False
...has my_debug_tag? True
Так что похоже PyQt является «потери» Питон объект он создал ранее, а затем делает " новый "по одному для каждого повторного доступа. Это ожидалось?
BTW, эта тестовая программа ведет себя одинаково как на Mac OS X (10.7), так и на Linux (Ubuntu 12). Я использую PyQt 4.8.5.
Мне было интересно, если обертки собирали мусор, поэтому я попробовал 'gc.disable()'. Но, подумав немного больше, очевидно, что это не повлияет. Сборщик мусора здесь не играет, поскольку счетчик ссылок падает до нуля. Спасибо за указание на это! –
И спасибо за отзыв о свойствах. Это определенно правильный способ исправить мою проблему. –
«Очевидно, что этот метод будет работать только для классов Qt, которые наследуют« QObject ». Из любопытства существуют ли классы Qt, которые * не * наследуют от 'QObject'? Или вы просто указываете, что это не будет работать для простых классов Python? –