ThomasB
ThomasB

Reputation: 63

Tracing custom tkinter is lagging

enter image description here

I have some issues with custom tkinter's performance due to the trace method. I have one trace method in a class App there traces all of my StringVars. But I also have a method there keeps track of which tab there is open (‘Forside’, ‘Lastarrangement’, ‘Pulttag’, ‘Sadeltag’) so the trace methods only trace the StringVars attached to the corresponding tab. See the screenshots that I've attached to this question.

My issue is, if there are too many StringVars to one of the tabs, in my case the ‘Sadeltag’ tab, then the program is lagging heavily.

Personally, I don't think that the 9 StringVars the program needs to trace in the ‘Sadeltag’ tab is much, but apparently for my program it is. But again, I'm kind of a noob, and I’m only scratching the surface of the programming world.

So, my question: is this just too much for a custom tkinter application to handle, or do I have some major design flaws in my code structure?

My goal with the application is to have a program that updates dynamically when the variables change their values.

def trace_string_vars(self, *args):
        for tab in self.current_state.keys():
            # Tracing Forside
            if tab == 'Forside' and self.current_state[tab]:
                pass
            # Tracing Lastarrangement
            elif tab == 'Lastarrangement' and self.current_state[tab]:
                # entry_C_t
                C_t = self.string_vars['entry_C_t'].get()
                if len(C_t) == 2 and C_t[0] == '0' and C_t[1] != '.' or len(C_t) > 0 and C_t[0] == '.':
                    self.string_vars['entry_C_t'].set('0')
                try:
                    C_t = float(C_t)
                    if C_t > 1:
                        self.string_vars['entry_C_t'].set('1.0')
                except ValueError:
                    self.string_vars['entry_C_t'].set('')

                # label_C_top
                topografi = self.string_vars['combobox_C_top'].get()
                C_top = 1.00
                if topografi == 'Afskærmet':
                    C_top = 1.25
                elif topografi == 'Normal':
                    C_top = 1.00
                elif topografi == 'Vindblæst':
                    C_top = 0.80
                self.string_vars['label_C_top'].set(f'C_top\t=\t{C_top:.2f}')
                self.string_vars['label_C_top_screen'].set(f'\t\t{topografi}      \t\u21D2\tC_top = {C_top:.2f}')

                # entry l_1
                l_1 = self.string_vars['entry_l_1'].get()
                if len(l_1) == 2 and l_1[0] == '0' and l_1[1] != '.' or len(l_1) > 0 and l_1[0] == '.':
                    self.string_vars['entry_l_1'].set('')
                try:
                    l_1 = float(l_1)
                except ValueError:
                    self.string_vars['entry_l_1'].set('')

                # entry l_2
                l_2 = self.string_vars['entry_l_2'].get()
                if len(l_2) == 2 and l_2[0] == '0' and l_2[1] != '.' or len(l_2) > 0 and l_2[0] == '.':
                    self.string_vars['entry_l_2'].set('')
                try:
                    l_2 = float(l_2)
                except ValueError:
                    self.string_vars['entry_l_2'].set('')

                # entry h
                h = self.string_vars['entry_h'].get()
                if len(h) == 2 and h[0] == '0' and h[1] != '.' or len(h) > 0 and h[0] == '.':
                    self.string_vars['entry_h'].set('')
                try:
                    h = float(h)
                except ValueError:
                    self.string_vars['entry_h'].set('')

                # label C_s
                try:
                    C_s = 1.00
                    if topografi == 'Afskærmet':
                        C_s = 1.00
                        self.string_vars['label_C_s_screen'].set(f'\t\t{topografi}\t\u21D2\tC_s = 1.00')
                    elif 2 * h > l_1:
                        C_s = 1.00
                        self.string_vars['label_C_s_screen'].set('\t\t2 \u2022 h > l_1\t\t\u21D2\tC_s = 1.00')
                    else:
                        if l_2 <= 10 * h:
                            C_s = 1.00
                            self.string_vars['label_C_s_screen'].set('\t\t2 \u2022 h \u2264 l_1\t\tog\tl_2 \u2264 10 \u2022 h\t\u21D2\tC_s = 1.00')
                        elif l_2 >= 20 * h:
                            C_s = 1.25
                            self.string_vars['label_C_s_screen'].set('\t\t2 \u2022 h \u2264 l_1\t\tog\tl_2 \u2265 20 \u2022 h\t\u21D2\tC_s = 1.25')
                        else:
                            C_s = 1 + 0.025 * ((l_2 - 10 * h) / h)
                            self.string_vars['label_C_s_screen'].set(f'\t\t2 \u2022 h \u2264 l_1\t\tog\t10 \u2022 h < l_2 < 20 \u2022 h\t\t\u21D2\tC_s = 1 + 0.025 \u2022 ((l_2 - 10 \u2022 h) / h) = {C_s:.2f}')
                    self.string_vars['label_C_s'].set(f'C_s\t=\t{C_s:.2f}')
                except TypeError:
                    pass

                # label C_e
                C_e = C_top * C_s
                self.string_vars['label_C_e'].set(f'C_e\t=\t{C_e:.2f}')

            # Tracing Formfaktor
            elif tab == 'Tagudformning' and self.current_state['Forside'] == False:
                if tab == 'Tagudformning' and self.current_state['Lastarrangement'] == False:
                    for tagtype in self.current_state[tab].keys():
                        # Tracing Pulttag
                        if tagtype == 'Pulttag' and self.current_state[tab][tagtype]:
                            # Tagtype
                            self.tagudformning = self.string_vars['combobox_tagtype'].get()
                            if self.tagudformning in settings.TAGUDFORMNING_LIST:
                                self.formfaktor_button_click()
                            
                            # Brystværn
                            brystværn = self.pulttag_menu_frame.switch_bryst_pult.get()
                            if brystværn == 1:
                                self.string_vars['switch_bryst_pult'].set('Ja')
                            elif brystværn == 0:
                                self.string_vars['switch_bryst_pult'].set('Nej')

                            # entry_a_pult
                            a_pult = self.string_vars['entry_a_pult'].get()
                            if len(a_pult) == 2 and a_pult[0] == '0' and a_pult[1] != '.' or len(a_pult) > 0 and a_pult[0] == '.':
                                self.string_vars['entry_a_pult'].set('0')
                            try:
                                a_pult = float(a_pult)
                                if a_pult > 90:
                                    self.string_vars['entry_a_pult'].set('90.0')
                            except ValueError:
                                self.string_vars['entry_a_pult'].set('')

                            # label_u_pult
                            try:
                                if a_pult <= 30 or brystværn == 1:
                                    u_pult = 0.80
                                elif a_pult >= 60:
                                    u_pult = 0.00
                                else:
                                    u_pult = 0.8 * (60 - a_pult) / 30
                                self.string_vars['label_u_pult'].set(f'\u03BC_1\t=\t{u_pult:.2f}')
                            except TypeError:
                                pass
                            
                            # label_s_pult
                            try:
                                C_t = self.string_vars['entry_C_t'].get()
                                C_t = float(C_t)
                                C_e = self.string_vars['label_C_e'].get()[-4:]
                                C_e = float(C_e)
                                u_pult = self.string_vars['label_u_pult'].get()[-4:]
                                u_pult = float(u_pult)
                                s_pult = u_pult * C_e * C_t * 1
                                self.string_vars['label_s_pult'].set(f's\t=\t{s_pult:.2f} kN/m\u00B2')
                            except TypeError:
                                pass
                            
                            # canvas_pult01
                            self.update_canvas_pult01()
                            self.update_canvas_pult02()
                            
                        # Tracing Sadeltag
                        elif tagtype == 'Sadeltag' and self.current_state[tab][tagtype]:
                            # Tagtype
                            self.tagudformning = self.string_vars['combobox_tagtype'].get()
                            if self.tagudformning in settings.TAGUDFORMNING_LIST:
                                self.formfaktor_button_click()

                            # Brystværn
                            brystværn_v = self.sadeltag_menu_frame.switch_bryst_sadel_v.get()
                            if brystværn_v == 1:
                                self.string_vars['switch_bryst_sadel_v'].set('Ja')
                            elif brystværn_v == 0:
                                self.string_vars['switch_bryst_sadel_v'].set('Nej')

                            brystværn_h = self.sadeltag_menu_frame.switch_bryst_sadel_h.get()
                            if brystværn_h == 1:
                                self.string_vars['switch_bryst_sadel_h'].set('Ja')
                            elif brystværn_h == 0:
                                self.string_vars['switch_bryst_sadel_h'].set('Nej')

                            # entry_a_pult
                            a_sadel_v = self.string_vars['entry_a_sadel_v'].get()
                            if len(a_sadel_v) == 2 and a_sadel_v[0] == '0' and a_sadel_v[1] != '.' or len(a_sadel_v) > 0 and a_sadel_v[0] == '.':
                                self.string_vars['entry_a_sadel_v'].set('0')
                            try:
                                a_sadel_v = float(a_sadel_v)
                                if a_sadel_v > 90:
                                    self.string_vars['entry_a_sadel_v'].set('90.0')
                            except ValueError:
                                self.string_vars['entry_a_sadel_v'].set('')

                            a_sadel_h = self.string_vars['entry_a_sadel_h'].get()
                            if len(a_sadel_h) == 2 and a_sadel_h[0] == '0' and a_sadel_h[1] != '.' or len(a_sadel_h) > 0 and a_sadel_h[0] == '.':
                                self.string_vars['entry_a_sadel_h'].set('0')
                            try:
                                a_sadel_h = float(a_sadel_h)
                                if a_sadel_h > 90:
                                    self.string_vars['entry_a_sadel_h'].set('90.0')
                            except ValueError:
                                self.string_vars['entry_a_sadel_h'].set('')

                            # label_u_pult
                            try:
                                if a_sadel_v <= 30 or brystværn_v == 1:
                                    u_sadel_v = 0.80
                                elif a_sadel_v >= 60:
                                    u_sadel_v = 0.00
                                else:
                                    u_sadel_v = 0.8 * (60 - a_sadel_v) / 30
                                self.string_vars['label_u_sadel_v'].set(f'\u03BC_1\t=\t{u_sadel_v:.2f}')
                            except TypeError:
                                pass

                            try:
                                if a_sadel_h <= 30 or brystværn_h == 1:
                                    u_sadel_h = 0.80
                                elif a_sadel_h >= 60:
                                    u_sadel_h = 0.00
                                else:
                                    u_sadel_h = 0.8 * (60 - a_sadel_h) / 30
                                self.string_vars['label_u_sadel_h'].set(f'\u03BC_2\t=\t{u_sadel_h:.2f}')
                            except TypeError:
                                pass

                            # label_s_pult
                            try:
                                C_t = self.string_vars['entry_C_t'].get()
                                C_t = float(C_t)
                                C_e = self.string_vars['label_C_e'].get()[-4:]
                                C_e = float(C_e)
                                u_sadel_v = self.string_vars['label_u_sadel_v'].get()[-4:]
                                u_sadel_v = float(u_sadel_v)
                                s_sadel_v = u_sadel_v * C_e * C_t * 1
                                self.string_vars['label_s_sadel_v'].set(f's_1\t=\t{s_sadel_v:.2f} kN/m\u00B2')
                            except TypeError:
                                pass

                            try:
                                C_t = self.string_vars['entry_C_t'].get()
                                C_t = float(C_t)
                                C_e = self.string_vars['label_C_e'].get()[-4:]
                                C_e = float(C_e)
                                u_sadel_h = self.string_vars['label_u_sadel_h'].get()[-4:]
                                u_sadel_h = float(u_sadel_h)
                                s_sadel_h = u_sadel_h * C_e * C_t * 1
                                self.string_vars['label_s_sadel_h'].set(f's_2\t=\t{s_sadel_h:.2f} kN/m\u00B2')
                            except TypeError:
                                pass

enter image description here

I’ve only attached my method for the tracing of the StringVars, because I believe that’s within there my problem occurs.

I only have issues with the 'Sadeltag' tab, the other tabs runs perfectly fine.enter image description here

enter image description here

enter image description here

Upvotes: 0

Views: 184

Answers (1)

ThomasB
ThomasB

Reputation: 63

I know what I was doing wrong now. I had entry widgets which were connected to label widgets. And I traced them both with the trace method. So instead of the method to run only once then it will run twice instead. And with many entry widgets and label widgets set up this way it of course becomes very inefficient. So, I updated the label widgets with the configure method instead, and now it performs a lot better.

Upvotes: 1

Related Questions