Tkinter python在试图登录主线程的新线程上崩溃

时间:2017-05-11 08:08:23

标签: python multithreading tkinter

我创建了一个tkinter gui,当点击某些按钮时会执行一些耗时的操作。在我的案例中有两个主要问题,我认为导致tkinter以不和谐的方式崩溃。

1)我想将新线程的一些输出记录到在主线程上运行的滚动文本小部件中,我认为这不是一个好主意。现在我通过将一个TextHandler对象发送给线程来实现这一点(参见我的代码)

2)为了避免从新线程登录到主线程,我想知道线程什么时候完成,然后从主线程登录到文本小部件,但主循环如何知道,何时线程是在从按下按钮调用的函数中创建的吗?

class TextHandler(logging.Handler):

"""This class allows you to log to a Tkinter Text or ScrolledText widget"""

def __init__(self, text):
    # run the regular Handler __init__
    logging.Handler.__init__(self)
    # Store a reference to the Text it will log to
    self.text = text

def emit(self, record):
    msg = self.format(record)
    def append():

        self.text.configure(state='normal')

        self.text.insert(tkinter.END, msg + '\n')
        self.text.configure(state=DISABLED)
        # Autoscroll to the bottom
        self.text.yview(tkinter.END)
    # This is necessary because we can't modify the Text from other threads
    self.text.after(0, append)


class GUI(Frame):

def __init__(self, parent, logger, st):
....initialize stuff...


def _startComputations(self):

    if (self._paths == ""):
        self._logger.warn("No drive paths found, please add a path")
    else:
        if (self._flexinput == ""):
            self._logger.warn(self._flexinput)
            self._logger.warn("No file path,continuing with standard KM estimation")

        self.myThread = StandardUsecases(self._paths, self._input, 
                                     self._logger, self._standard_choices,
                                     self._numberOfoccurences_usecases, 
                                     self._all_logs, self._unique_countries,
                                     self.bt, self.bt2, self.bt3,
                                     self._flexinput)
        self.myThread.start()


        self._all_jsons = self.myThread._original_json_list
        self._general_json = self.myThread._general_json_data_list


def _KM_Button(self):

    self._all_logs[:] = []
    self.bt = Button(self.frame6, text='1-Main Usecases', font = "Helvetica 11 bold italic",
                command = self._startComputations,relief = RAISED, bd= 6, bg = "pale green", fg = 'black')
    self.bt.pack(side =  LEFT)

def initGUI(self):

    self.parent.title("DC Statistics calculator")

    self.pack(fill=BOTH, expand=True)   
    self._Drive_Paths()
    self._Flexray_Path()
    #self._UserInput()
    self._KM_Button()
    self._countButton()
    self._exportButton()
    self._helpButton()

def main():

root = Tk()
root.geometry("700x800+400+400")

st = scrolledtext.ScrolledText(root, state='disabled')
st.configure(font="Times 13")
st.pack(side=BOTTOM, fill='both',expand='yes')

text_handler = TextHandler(st)
logger = logging.getLogger()
logger.addHandler(text_handler)

app = GUI(root, logger, st)
root.mainloop()  

if __name__ == '__main__':
   main()

因此在按下按钮后,将调用_startComputations函数,并在那里创建线程。我发送_logger对象,以便我可以在新线程上登录ScrolledText小部件。但是大多数时候我遇到像“python.exe停止工作”或者用共享对象调用tcl_appendlimitedtoobj的崩溃。

如果我不想从新线程登录,主循环如何知道新线程是否完成,因为新线程是在按下按钮后调用的函数创建的?

谢谢

0 个答案:

没有答案