#python #pyqt5
#python #pyqt5
Вопрос:
Я просто пытаюсь отправить сигнал из класса A в класс B, но это не работает, я не вижу печати. Я, конечно, делаю что-то не так, но я знаю, что. Вот краткий код, который покажет вам проблему, спасибо.
from PyQt5 import QtWidgets, QtCore
import sys
class B(object):
def __init__(self, parent=None):
super(B, self).__init__(parent)
self._initSlot()
def _initSlot(self):
a = A()
a.assetSelectionChanged.connect(self._doSomething)
@QtCore.pyqtSlot()
def _doSomething(self):
print('do something')
class A(QtWidgets.QWidget):
assetSelectionChanged = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(A, self).__init__(parent)
self._initUI()
def _initUI(self):
self.treeWidgetAssets = QtWidgets.QTreeWidget()
for i in range(1, 11, 1):
QtWidgets.QTreeWidgetItem(self.treeWidgetAssets, [str(i)])
self.mainLayout = QtWidgets.QVBoxLayout()
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.treeWidgetAssets)
self.treeWidgetAssets.itemSelectionChanged.connect(self.onAssetSelectionChanged)
def onAssetSelectionChanged(self):
self.assetSelectionChanged.emit()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dlg = A()
dlg.show()
sys.exit(app.exec_())
Ответ №1:
С этим кодом возникают различные проблемы:
- Экземпляр
B
никогда не создается - прямые
object
подклассы не требуют вызоваsuper().__init__()
, и даже если вы это сделаете, вам, конечно, не следует добавлять произвольные аргументы, поскольку они не будут приняты, что приведет к сбою B
должен наследовать от QObject- Новый экземпляр не должен быть объявлен в
_initSlot
: он уже существует, и тот, который вы там создаете, будет немедленно собран мусором, потому что его ссылка является локальной и будет удалена сразу после_initSlot
возврата
class B(QtCore.QObject):
def __init__(self, parent=None):
super(B, self).__init__(parent)
self._initSlot()
def _initSlot(self):
if self.parent():
self.parent().assetSelectionChanged.connect(self._doSomething)
@QtCore.pyqtSlot()
def _doSomething(self):
print('do something')
class A(QtWidgets.QWidget):
assetSelectionChanged = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(A, self).__init__(parent)
self._initUI()
self.b = B(self)
# ...
Комментарии:
1. Спасибо за вашу помощь и объяснение!
Ответ №2:
Как вариант. Я отметил строки, которые я изменил для вас.
import sys
from PyQt5 import QtWidgets, QtCore
class B(QtCore.QObject):
def __init__(self, parent=None):
super(B, self).__init__(parent)
# self._initSlot()
# def _initSlot(self):
# a = A()
# a.assetSelectionChanged.connect(self._doSomething)
@QtCore.pyqtSlot(str)
def _doSomething(self, text):
print(f'do something: clicked -> {text}')
class A(QtWidgets.QWidget):
assetSelectionChanged = QtCore.pyqtSignal(str) # 1. str
def __init__(self, parent=None):
super(A, self).__init__(parent)
self._initUI()
self.b = B(self) # !!!
self.assetSelectionChanged[str].connect(self.b._doSomething) # 3. str
def _initUI(self):
self.treeWidgetAssets = QtWidgets.QTreeWidget()
for i in range(1, 11, 1):
QtWidgets.QTreeWidgetItem(self.treeWidgetAssets, [str(i)])
self.mainLayout = QtWidgets.QVBoxLayout()
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.treeWidgetAssets)
self.treeWidgetAssets.itemSelectionChanged.connect(self.onAssetSelectionChanged)
def onAssetSelectionChanged(self):
text = self.treeWidgetAssets.selectedItems()[0].text(0)
self.assetSelectionChanged.emit(text) # 2. text
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dlg = A()
dlg.show()
sys.exit(app.exec_())
Комментарии:
1. Поскольку для сигнала существует только одна перегрузка, нет необходимости указывать его с
[str]
помощью .2. Спасибо за вашу помощь! Излучение сигнала с помощью str определенно упростит мой код 🙂