How to connect functions to dynamically created QP

2019-09-20 15:44发布

问题:

This question already has an answer here:

  • Passing extra arguments through connect 1 answer

I am adding QPushButtons to every row in a QTableWidget dynamically.

When I click a button I want it to open a link based on data in the same row.

I can only get it to work if I first select the row, then click the button.

I want to be able to click the button without having to click the row first.

This is a snippet of what I have:

def populate_table(self):
    instances = []

    table = self.ui.ESC_tableWidget
    table.setRowCount(0)


    button_dict = {}

    for esc_inst in instances:
        button_dict[esc_inst.esc_id] = QtWidgets.QPushButton('Open link')
        rowPosition = table.rowCount()
        table.insertRow(rowPosition)
        table.setItem(rowPosition , 0 , QtWidgets.QTableWidgetItem(esc_inst.esc_id))
        .
        .
        .
        esc_table.setCellWidget(rowPosition, 5 , button_dict[esc_inst.esc_id] )



    for button in button_dict.values():
        button.clicked.connect(self.open_link)



def open_link(self):
    selected_esc_id = table.item(table.currentRow(), 0).text()

So I need to bypass the table.currentRow() function, because that returns the correct row number if a row IS selected. If I directly click a button without selecting the row first, the previously selected row number is returned.

I can only think of hacky solutions like creating an orderedDict or such, but it seems like such a trivial thing that I am sure I am missing something.

Any ideas how to overcome this?

回答1:

You can have your button click callback receive some arguments that define what button it is. When attaching the callback to the buttons, create a separate lambda function for each button that calls your callback, but with an index:

for i, button in enumerate(button_dict.values()):
        button.clicked.connect(lambda checked, i=i: self.open_link(i))

And then, in your callback:

def open_link(self, i):
    selected_esc_id = table.item(i, 0).text()

You need the i=i-part in the lambda because, otherwise, it will just pass the last value of i to your callback. With that part included, every button will pass a different i to your callback method.



标签: python pyqt5