Как определить откуда излучается сигнал в PyQt6?

Рейтинг: 1Ответов: 1Опубликовано: 10.08.2023

Я решил отделить функции логики в отдельный класс Action(), но мне не удается получить отправителя сигнала через sender().
Сейчас он работает корректно только при открытии нового окна (Second), но я хотел чтобы при вызове функции из класса Action она получала отправителя сигнала.

Как в этом куске:

class Action():
           
    def pushBtn(self):
        sender = self.sender()
        print(sender.text()) 
        dlg = SecondDialog()
        dlg.exec()

Если функция в классе MainWindow(), то все работает нормально. как это сделать и как правильно отделить логику в другой класс?

Здесь упрощенный пример:

import sys
from PyQt6.QtGui import QClipboard
from PyQt6.QtWidgets import (QWidget, QApplication, QPushButton,
                             QHBoxLayout, QVBoxLayout, QDialog)

class MainWindow(QWidget):
    
    def __init__(self, parent=None):
        super().__init__()
        self.setGeometry(150, 300, 300, 150)
        self.setWindowTitle('MAIN')
        self.initUI()
        self.act_widgets()
        self.show()
        
    def initUI(self):
        self.vbMain = QVBoxLayout()
        self.btn = QPushButton('MAIN')
        self.btn1 = QPushButton('MAIN1')
        self.vbMain.addWidget(self.btn)
        self.vbMain.addWidget(self.btn1)
        self.setLayout(self.vbMain)
        
    def act_widgets(self):
        self.btn.clicked.connect(Action.pushBtn)
        self.btn1.clicked.connect(Action.pushBtn)
    
class SecondDialog(QDialog):
    
    def __init__(self):
        super().__init__()
        self.setWindowTitle('SECOND')
        self.setGeometry(150, 300, 150, 150)
        self.initUIDialog()
        self.act_widgets_dialog()
        self.show()
        sender = self.sender()
        print(sender.text())        
        
    def initUIDialog(self):
        self.vbSec = QVBoxLayout()
        self.btnSec = QPushButton('SEC')
        self.vbSec.addWidget(self.btnSec)
        self.setLayout(self.vbSec)
    
    def act_widgets_dialog(self):
        self.btnSec.clicked.connect(Action.pushSecBtn)

class Action():
           
    def pushBtn(self):
        dlg = SecondDialog()
        dlg.exec()
        
    def pushSecBtn():
        pass

app = QApplication(sys.argv)
MainWnd = MainWindow()
sys.exit(app.exec())

Ответы

▲ 1Принят

Я не уверен что правильно понимаю то, что вы хотите сделать.

Обратите внимание на строки помеченные как # !!! <---

import sys
'''
from PyQt6.QtGui import QClipboard
from PyQt6.QtWidgets import (QWidget, QApplication, QPushButton,
                             QHBoxLayout, QVBoxLayout, QDialog)
'''
from PyQt5.Qt import *

   
class SecondDialog(QDialog):
    signal = pyqtSignal(object)                                           # !!! <---

    def __init__(self, btn):                                              # + btn
        super().__init__()
        self.btn = btn                                                    # +++
        print(f'class SecondDialog: {btn.text()}\n')                      #  
        
        self.setWindowTitle('SECOND')
# ?        self.setGeometry(150, 300, 150, 150)
        self.resize(150, 150)
        
        self.initUIDialog()
#        self.act_widgets_dialog()
#        self.show()
#        sender = self.sender()
        
    def initUIDialog(self):
        self.btnSec = QPushButton('SEC')
        self.btnSec.clicked.connect(self.act_widgets_dialog)              # +++
        self.vbSec = QVBoxLayout(self)        
        self.vbSec.addWidget(self.btnSec)
    
    def act_widgets_dialog(self):
#        self.btnSec.clicked.connect(Action.pushSecBtn)
        self.signal.emit(self.btn)                                        # !!! <---

class Action():
    def __init__(self):
        super().__init__()
           
    def pushBtn(self, btn):                                               # + btn
        print(f'\nclass Action():     {btn.text()}')                      #
        
        self.dlg = SecondDialog(btn)                                      # + btn
        self.dlg.signal.connect(self.pushSecBtn)                          # !!! <---
        
        x = btn.parent().geometry().x() + btn.parent().geometry().width()  + 20
        y = btn.parent().geometry().y() - 30
        self.dlg.move(x, y)
        
        self.dlg.exec()
        
    def pushSecBtn(self, btn):
        print(f'def pushSecBtn():   {btn.text()} ----> {self.dlg.btnSec.text()}') # +
        

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
# ?        self.setGeometry(150, 300, 300, 150)
        self.resize(300, 150)
        self.setWindowTitle('MainWindow')
        
        self.initUI()
        
        self._action = Action()                                           # !!! +++
        
        self.act_widgets()
        
    def initUI(self):
        self.btn = QPushButton('MAIN')
        self.btn1 = QPushButton('MAIN1')
        self.vbMain = QVBoxLayout(self)        
        self.vbMain.addWidget(self.btn)
        self.vbMain.addWidget(self.btn1)
        
    def act_widgets(self):
#        self.btn.clicked.connect(Action.pushBtn)
#        self.btn1.clicked.connect(Action.pushBtn)
        self.btn.clicked.connect(
            lambda ch, btn=self.btn: self._action.pushBtn(btn))           # !!! +++
        self.btn1.clicked.connect(
            lambda ch, btn=self.btn1: self._action.pushBtn(btn))          # !!! +++
        

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec())

введите сюда описание изображения

Спросите если вам что-то не понятно.