1

Im doing a software with Python3.6, PyQt4 and SQlite3. The software consist in a number of students each of them with their data (unique id, name, surname, address, etc.) The GUI has a list menu, were the list of all the students is shown.

In the list itself, I iterate depending on how many students I have. The layout is made and it creates a name, and 2 QPushButtons (one to generate a PDF and other to delete the student data)

Here is an example

In my code, I have every "Generate a PDF" button of each student in the list on a python list, also for the "Delete student" buttons. My problem is when I give the buttons the .clicked.connect(function)

for i in range(0, len(self.list_menu.delete_button_list)):
    self.list_menu.delete_button_list[i].clicked.connect(
        lambda: self.delete_student_data(self.list_menu.id_list[i]))

For example, I have 3 students on the list, so button 1 should recieve id:1 self.delete_student_data(1), then button_2 with id=2 and button_3 with id:=3. But from what I've understood, what .connect() recieves does not execute, not until the button is actually clicked in this case. So at the moment .connect() is called, the value i is 3 in this example. Hence every button call the self.delete_student_data with id=3.

I see that there is no way to make this work like I pretend to.

Hope its clear the way I described it. Thanks!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
juanga13
  • 11
  • 4
  • A tip for tagging in SO: always include the language tag (ie. “python”), if your issue is specific to python 3.6, add both tags, as “python-3.6” is an add-on tag to “python”. More people will read/answer your question when it’s properly tagged, since we usually only hangout in the “python” tag section. (I have edited your tag for this question, be aware next time) – Taku Sep 04 '17 at 23:50
  • 1
    Use a default argument: `connect(lambda arg, i=i: ...` (NB: the `arg` param is needed because the clicked signal always sends its checked state). – ekhumoro Sep 05 '17 at 01:28
  • @ekhumoro I didn't understood the `arg` you are referring to, where arg is used? in my delete_student_data function? Thanks for the reply – juanga13 Sep 07 '17 at 17:22
  • @juanga13. You don't need to use it. But it has to be there, otherwise the signal would overwrite your `i` argument with a boolean value. The rest of your current `lambda` function can stay exactly the same. – ekhumoro Sep 07 '17 at 17:30

1 Answers1

0

I resolved the problem by using functools.partial module. As from what I understand, partial takes the argument of the function and 'freezes' it. Maybe someone knows better this whole behavior and can explain it better. Here is the documentation.

Now the code is the following:

for i in range(0, len(self.list_menu.delete_button_list)):
button = self.list_menu.delete_button_list[i]
button.clicked.connect(partial(self.delete_student_data, button))
juanga13
  • 11
  • 4