Python PyQt4,如何一次添加一批小部件(QPushButton),并让它们在插槽上执行

Python PyQt4,如何一次添加一批小部件(QPushButton),并让它们在插槽上执行,python,pyqt,signals,sender,Python,Pyqt,Signals,Sender,如果我想一次添加10个QPushButton: NumCount=20 for i in range(NumCount): btn=QPushButton("%s %s" %("Button" i+1),self) btn.clicked.connect(self.btnclick) def btnclick(self): # here is my question # how to define which button clicked? # how to print

如果我想一次添加10个QPushButton:

NumCount=20
for i in range(NumCount):
  btn=QPushButton("%s %s" %("Button" i+1),self)
  btn.clicked.connect(self.btnclick)

def btnclick(self):
  # here is my question 
  # how to define which button clicked?
  # how to print btn.text?

如def中所述(单击)

当您在插槽中时,可以使用sender()方法(只需调用self.sender()),您将收到一个对对象的引用,该对象发出信号。是关于它的文档。

我将子类化
QPushButton
,并定义我自己的发送者和插槽。
QObject.sender()
方法很吸引人,但它给我带来了麻烦

class MyPushButton(QPushButton):
    def __init__(self, text = '', parent = None):
        QPushButton.__init__(self, text, parent)
        self.clicked.connect(self._handle_click)

    my_click = QtCore.pyqtSignal(QObject)

    def _handle_click(self):
        my_click.emit(self)

def btnclick(btn):
    print 'Handle button %s' % btn

for i in xrange(20):
    btn = MyPushButton('%s %s' % ('Button', i + 1), self)
    btn.my_click.connect(btnclick)
一种稍微有点python风格的方法可以定义类内的行为,如下所示:

class MyPushButton(QPushButton):
    def __init__(self, button_number, parent = None):
        QPushButton.__init__(self, '%s %s' % ('Button', button_number), parent)
        self.button_number = button_number
        self.clicked.connect(self._handle_click)

     def _handle_click(self):
        print 'Handle button %s' % self

for i in xrange(20):
    btn = MyPushButton(i + 1, self)

正如格鲁西奇所说,有自我。(在QObject中)以获得确切的信息

还有一个类提供了从几个信号发送器到一个插槽的高级映射。它有助于多对一信号/插槽映射的基本情况


Chris B关于定义一个将发送方作为参数传输的新插槽的建议有点复杂,但在程序结构和类之间的分离方面更清晰。当目标槽位于另一个对象中时,我倾向于使用该方法。对于类的私有槽内的映射,sender()既简洁又非常合适,我认为。

下面是一个小应用程序,演示了一种可能的解决方案:

from PyQt4.QtGui import QPushButton, QWidget
from PyQt4.QtGui import QVBoxLayout, QApplication

def smart_connect(btn, btn_click_slot):
    proxy_slot = lambda checked: btn_click_slot(btn)
    btn.clicked.connect(proxy_slot)

class MyWidget(QWidget):
    btn_count = 4
    def __init__(self):
        super(MyWidget, self).__init__()
        lt = QVBoxLayout(self)
        for i in range(self.btn_count):
            btn = QPushButton("Button %s"%(i+1))
            smart_connect(btn, self.btn_click)
            lt.addWidget(btn)
    def btn_click(self, btn):
        print "Button '%s' was clicked."%btn.text()

app = QApplication([])
wgt = MyWidget()
wgt.show()
app.exec_()

请欣赏:)

说真的,发件人()没有问题。我用过很多次,效果很好。然而,我们应该谨慎行事。我通常在外部(即向其他对象)发送信号时使用您的方法,但在类内部路由信号时使用sender()。sender()可能没有任何问题,但正如文档所述,这“违反了面向对象的模块化原则”。不可否认,这不会导致任何人死亡。我可能会想用它作为一个“快速和肮脏”的修复。但是Python使得做得更好、更干净变得非常容易,从长远来看,只要做得正确,可能会更好。