自定义 tkinter 跟踪延迟

0 投票
1 回答
54 浏览
提问于 2025-04-13 20:03

我在使用自定义的tkinter时遇到了一些性能问题,这主要是因为trace方法的原因。我在一个叫做App的类里有一个trace方法,它会追踪我所有的StringVars(字符串变量)。同时,我还有一个方法用来记录当前打开的是哪个标签(‘Forside’,‘Lastarrangement’,‘Pulttag’,‘Sadeltag’),这样trace方法就只会追踪与当前标签相关的StringVars。你可以看看我附上的图片。

我的问题是,如果某个标签下的StringVars太多,比如我这个‘Sadeltag’标签下的StringVars数量比较多,程序就会变得很卡。我个人觉得‘Sadeltag’标签下需要追踪的9个StringVars并不算多,但对我的程序来说似乎就是太多了。不过,我还是个新手,对编程的理解还很浅。

所以,我想问的是,这对于一个自定义的tkinter应用来说是不是太复杂了,还是说我的代码结构设计上有一些大的问题?

我希望这个应用能够在变量值变化时动态更新。

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

我只附上了追踪StringVars的方法,因为我觉得问题可能出在这里。

我只在‘Sadeltag’标签下遇到问题,其他标签运行得很好。enter image description here

enter image description here

enter image description here

1 个回答

1

我现在知道我之前做错了什么。我有一些输入框(entry widgets),它们和标签框(label widgets)连接在一起。我用了一种叫做trace的方法来跟踪它们。结果是,这个方法本来应该只运行一次,但实际上却运行了两次。因为我设置了很多这样的输入框和标签框,所以效率变得很低下。后来,我改用了configure方法来更新标签框,现在效果好多了。

撰写回答