开发者

PyQt4,How to add a batch of widget (QPushButton) at one time and lets them to execute on SLOT

if i want to add 10 QPushButton at one time:

NumCount=20
for i in range(NumCount):
  btn=QPushButton("%s %s" %("Button" i+1),self)
  btn.clicked.conn开发者_如何学Pythonect(self.btnclick)

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

as stated in the def(btnclick).


When you are in a slot, you can use sender() method (just call self.sender()) and you will receive a reference to the object, from which signal was emitted. Here is documentation about it.


I'd subclass QPushButton and define my own sender and slot. The QObject.sender() method is tempting, but it gives me the heebie-jeebies.

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)

A slightly more Pythonic way of doing this could define the behavior within the class, like so:

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)


As gruszcsy said, there's self.sender() (in QObject) to get that exact info.

There's also the QSignalMapper class that provides a higher-level mapping from several signal senders to one slot. It helps for the basic cases of many-to-one signal/slot mapping.

Chris B's suggestion about defining a new slot that transmits the sender as a parameter is a bit more complicated, but cleaner in terms of program structure and separation between classes. I tend to use that method when the target slot is in another object. For mapping inside a class's private slot, sender() is both neat and quite appropriate, IMO.


Here is a small app demonstrating one possible solution:

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_()

Please enjoy :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜