Getting event from buttons generated by for loop in wxpython

39 Views Asked by At

Good day @all. I hope your day was great? I also really want to thank everyone that contributed toward helping me solved the problem I had when I posted last time. Today, I have a problem and it has to do with bunch of buttons I had th almighty for loop generate for me. The buttons will be generated along side labels like this: For student A => nameof_studentA_label, Scoreof_studentA and the end of the row the button => nameof_studentB_label, Scoreof_studentB and the end of the row the button. ....... Trouble is I couldn't get get their event to work. To be specific, whenever I clicked any of the button apart from the first button I don't get any action.

What I wanted doing is to fetch rows of record from an sqlite database and display the fields and a button with the label "Display Record" event will call a method I named "view_student_exam_record" and somehow get the info that matches the info from the database that were matched to the button. The event will fire after I clicked on any of the for-loop-generated-loop.

Below is the code that fetch the record and generate the labels and button using for loop.

def search_exam_record(self, event):
        count=0
        if self.search_exam_class_name_text.GetValue()!="" and self.search_exam_term_name_text.GetValue()!="" and self.search_exam_session_name_text.GetValue()!="":
            #search_exam_record = SchoolManagementSystem.retrieve_data(SchoolManagementSystem, "exam", "*", "where class=? and term =? and session=?", (self.search_exam_class_name_text.GetValue().lower(), self.search_exam_term_name_text.GetValue(), self.search_exam_session_name_text.GetValue()))
            search_exam_record=cursor.execute("select *, rank() over(order by total_scores desc) as rank from exam where class=? and term=? and session=? ", (self.search_exam_class_name_text.GetValue().lower(), self.search_exam_term_name_text.GetValue(), self.search_exam_session_name_text.GetValue()))
            
            self.sub_dict = {}
            count_list = []
            self.student_name_list = []
            self.student_id_list = []
            self.total_score_list = []
            self.average_list = []
            self.rank_list = []
            self.view_button_list = []
            self.button_id = []
            for exam_record in search_exam_record:
                
                student_name = exam_record['studentname']
                studentid = exam_record['student_id']
                subject_dict_str = exam_record['scores']
                
                subject_dict = eval(subject_dict_str)
                self.subject_list = list(subject_dict.keys())
                
                self.subject_score_list = list(subject_dict.values())
                total_score= exam_record['total_scores']
                rank = exam_record['rank']
                rank = str(rank)
                average_score = total_score/len(subject_dict)
                average_score = round(average_score, 2)
                if rank[-1]=='1':
                    rank = rank+'st'
                elif rank[-1]=='2':
                    rank = rank+'nd'
                elif rank[-1] =='3':
                    rank = rank+'rd'
                else:
                    rank = rank+'th'
                self.button_id.append(wx.NewId())
                name_heading = wx.StaticText(self.panel2, label="Name")
                id_heading = wx.StaticText(self.panel2, label="Student Id")
                total_heading = wx.StaticText(self.panel2, label="Total Score")
                average_heading = wx.StaticText(self.panel2, label="Average")
                position_heading = wx.StaticText(self.panel2, label="Position")
                empty_heading = wx.StaticText(self.panel2, label="")
                studentname_label = wx.StaticText(self.panel2, label=student_name)
                studentid_label = wx.StaticText(self.panel2, label=str(studentid))
                student_total_scores = wx.StaticText(self.panel2, label=subject_dict_str)
                totalscore_label = wx.StaticText(self.panel2, label=str(total_score))
                average_label = wx.StaticText(self.panel2, label=str(average_score))
                rank_label = wx.StaticText(self.panel2, label=rank)
                self.view_button = wx.Button(self.panel2, self.button_id[count], label="Display Record")
                self.student_name_list.append(studentname_label)
                self.student_id_list.append(studentid_label)
                self.total_score_list.append(totalscore_label)
                self.average_list.append(average_label)
                self.rank_list.append(rank_label)
                
                count_list.append(count)
                
                self.view_button_list.append(self.view_button)
                self.button_id.append(self.view_button_list[count].GetId())
                self.view_button_list[count].Bind(wx.EVT_BUTTON, lambda event, count=count: self.view_student_exam_record(event, count, self.sub_dict))
                self.sub_dict[self.view_button_list[count].GetId()]:[count+1, studentid_label.GetLabel(), studentname_label.GetLabel(), totalscore_label.GetLabel(), average_label.GetLabel(), rank_label.GetLabel() ]
            
                if count==0:
                            
                            self.search_exam_result_grid_sizer.AddMany(
                                [
                                    (name_heading, 0, wx.ALL, 5),
                                    (id_heading, 0, wx.ALL, 5),
                                    (total_heading, 0, wx.ALL, 5),
                                    (average_heading, 0, wx.ALL, 5),
                                    (position_heading, 0, wx.ALL, 5),
                                    (empty_heading, 0, wx.ALL, 5),
                                    

                                    (studentname_label, 0, wx.ALL, 5),
                                    (studentid_label, 0, wx.ALL, 5),
                                    (totalscore_label, 0, wx.ALL, 5),
                                    (average_label, 0, wx.ALL, 5),
                                    (rank_label, 0, wx.ALL, 5),
                                    (self.view_button, 0, wx.ALL, 5),
                                ]
                                )
                        
                else:
                    
                            
                            self.search_exam_result_grid_sizer.AddMany(
                                    [
                                        (studentname_label, 0, wx.ALL, 5),
                                        (studentid_label, 0, wx.ALL, 5),
                                        (totalscore_label, 0, wx.ALL, 5),
                                        (average_label, 0, wx.ALL, 5),
                                        (rank_label, 0, wx.ALL, 5),
                                        (self.view_button, 0, wx.ALL, 5),
                                    ]
                                )
                            

                    
            count+=1
            
            
            
        else:
            print("Please fill the required field")
        self.panel2.SetSizer(self.search_exam_result_grid_sizer)
        print(len(self.sub_dict))

And below is the code that get the event fired from the for-loop-generated-button

def view_student_exam_record(self, event, index, sub_dict):
        button_id = event.GetEventObject()
        button_id = button_id.GetId()
        print(button_id)
        counter=0
        search_student_record=cursor.execute("select student_id, dob, parentaddress, gender, place, lgaoforigin, stateoforigin, nationality, parent, passportdir from student where student_id=? ", (index,))
        print(index)
        search_student_exam_record=cursor.execute("select student_id, scores, total_scores, class, term, session from exam where student_id=? ", (index,))
        for student_record in search_student_record:
            counter+1
            student_id = student_record['student_id']
            print(student_id)
            student_dob = student_record['dob']
            
            student_gender = student_record['gender']
            student_town_village = student_record['place']
            student_lga = student_record['lgaoforigin']
            student_state = student_record['stateoforigin']
            student_nationality = student_record['nationality']
            parent = student_record['parent']
            passportfolder = student_record['passportdir']
            studentname_label =  wx.StaticText(self, label=self.student_name_list[index].GetLabel())
            studentid_label = wx.StaticText(self, label=str(self.student_id_list[index].GetLabel()))
            studentdob_label =  wx.StaticText(self, label=student_dob)
            studentgender_label = wx.StaticText(self, label=student_gender)
            studenttown_label = wx.StaticText(self, label=student_town_village)
            studentlga_label = wx.StaticText(self, label=student_lga)
            studentstate_label = wx.StaticText(self, label=student_state)
            studentnationality_label =  wx.StaticText(self, label=student_nationality)
            parent_label = wx.StaticText(self, label=parent)
            self.right_grid_box.AddMany(
                [
                 (studentname_label, 0, wx.ALL, 5),
                 (studentid_label, 0, wx.ALL, 5),
                 (studentdob_label, 0, wx.ALL, 5),
                 (studentgender_label, 0, wx.ALL, 5),
                 (studenttown_label, 0, wx.ALL, 5),
                 #(studenttown_label, 0, wx.ALL, 5),
                 (studentlga_label, 0, wx.ALL, 5),
                 (studentstate_label, 0, wx.ALL, 5),
                 (studentnationality_label, 0, wx.ALL, 5),
                 (parent_label, 0, wx.ALL, 5),
                 
                 
            
                ]

                )
        print(index)
        self.sub_lis = []
        if len(search_student_exam_record.fetchall())>0:
            pass
        else:
            pass
        print(search_student_exam_record.fetchall())
        
        sub_index=0
        for subject in self.subject_list:
            
            subject_label =  wx.StaticText(self, label=self.subject_list[sub_index])
            test1_label = wx.StaticText(self, label=str(self.subject_score_list[sub_index][0]))
            test2_label =  wx.StaticText(self, label=str(self.subject_score_list[sub_index][1]))
            test3_label = wx.StaticText(self, label=str(self.subject_score_list[sub_index][2]))
            exam_label = wx.StaticText(self, label=str(self.subject_score_list[sub_index][3]))
            total_exams_score_label = wx.StaticText(self, label=str(self.subject_score_list[sub_index][4]))
            total_score_label = wx.StaticText(self, label=str(self.total_score_list[sub_index].GetLabel()))
            average_score_label = wx.StaticText(self, label=str(self.average_list[sub_index].GetLabel()))
            position_label = wx.StaticText(self, label=self.rank_list[sub_index].GetLabel())
            self.right_grid_box2.AddMany(
                [
                 (subject_label, 0, wx.ALL, 5),
                 (test1_label, 0, wx.ALL, 5),
                 (test2_label, 0, wx.ALL, 5),
                 (test3_label, 0, wx.ALL, 5),
                 (exam_label, 0, wx.ALL, 5),
                 (total_exams_score_label, 0, wx.ALL, 5),
                 (total_score_label, 0, wx.ALL, 5),
                 (average_score_label, 0, wx.ALL, 5),
                 (position_label, 0, wx.ALL, 5),
            
                ]

                )
            sub_index+=1
        self.SetSizer(self.right_box_sizer)

I hope I am clearn enough.

1

There are 1 best solutions below

5
Psionman On

Here's a simple app to show the principle. You need to assign an id to every button and you can retrieve it in the bound event using event.GetEventObject().GetId()

import wx

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(None, *args, **kwargs)
        self.Title = 'Wx App'

        self.panel = MainPanel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.panel)
        self.SetSizer(sizer)
        self.Center()
        self.Show()


class MainPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        sizer = wx.BoxSizer(wx.VERTICAL)
        # One button for each student
        for index in range(5):
            button = wx.Button(self, label=f'Button {index}', id=index)
            button.Bind(wx.EVT_BUTTON, self.get_record)
            sizer.Add(button)
        self.SetSizer(sizer)

    def get_record(self, event):
        print(event.GetEventObject().GetId())
        # Do your database lookup here


if __name__ == '__main__':
    wx_app = wx.App()
    MainFrame()
    wx_app.MainLoop()