Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2.7 避免GUI冻结_Python 2.7_Tkinter_Python Multithreading - Fatal编程技术网

Python 2.7 避免GUI冻结

Python 2.7 避免GUI冻结,python-2.7,tkinter,python-multithreading,Python 2.7,Tkinter,Python Multithreading,我开发了一个简单的Python应用程序,做了一些工作,然后我决定使用Tkinter添加一个简单的GUI 问题是,当我调用一个名为startprocess的函数并开始做一些处理器很重的事情时,窗口会冻结 我知道这是一个常见的问题,我已经读到我应该使用非常复杂的多线程,因为该函数也会更新GUI,或者将我的代码划分为不同的函数,每个函数工作一段时间。无论如何,下面的代码中是否需要任何修改以避免GUI冻结 import threading import tkinter as tk from tkinte

我开发了一个简单的Python应用程序,做了一些工作,然后我决定使用Tkinter添加一个简单的GUI

问题是,当我调用一个名为startprocess的函数并开始做一些处理器很重的事情时,窗口会冻结

我知道这是一个常见的问题,我已经读到我应该使用非常复杂的多线程,因为该函数也会更新GUI,或者将我的代码划分为不同的函数,每个函数工作一段时间。无论如何,下面的代码中是否需要任何修改以避免GUI冻结

import threading
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
import os, datetime, sys, subprocess
import parselog_v1


# diplay messagebox window
def MessageBox(windowLable,msg):
   messagebox.showinfo(windowLable, msg)


# check if Dir empty
def checkDirEmpty(work_path):
    if os.path.isdir(work_path):
        if not os.listdir(work_path):
            print ("No Files found in directory")
            MessageBox('Log Parser', 'No Files found in directory.')
        else:
            return True



# launch app in center of screen
def center_window(width=300, height=200):
    # get screen width and height
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    # calculate position x and y coordinates
    x = (screen_width/2) - (width/2)
    y = (screen_height/2) - (height/2)
    root.geometry('%dx%d+%d+%d' % (width, height, x, y))

# application frame

class Application(tk.Frame):

    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.pack()
        self.createWidgets()
        self.master.title("Log Parser")

    def createWidgets(self):
        self.Run_Main = tk.Button(self)
        self.Run_Main["text"] = "Browse for logs"
        self.Run_Main["fg"] = "blue"
        self.Run_Main["command"] = self.startProcess
        self.Run_Main.pack(side='left',padx=0)

        self.QUIT = tk.Button(self)
        self.QUIT["text"] = "Quit!"
        self.QUIT["fg"]   = "red"
        self.QUIT["command"] =  self.quit
        self.QUIT.pack(side='right',padx=5)

    def startProcess(self):
        global Src_foldername
        Src_foldername = filedialog.askdirectory()
        Src_foldername = Src_foldername.replace("/", "\\")
        print("Source folder: " + Src_foldername)
        if checkDirEmpty(Src_foldername):
            # process logs
            # multithread
            print("Processing...")
            self.refresh()
            threading.Thread(target=parselog_v1.main(Src_foldername))



# scroll text inside application frame
class scrollTxtArea:

    def __init__(self, root):
        frame = tk.Frame(root)
        frame.pack()
        self.textPad(frame)
        return

    class IORedirector(object):
        '''A general class for redirecting I/O to this Text widget.'''
        def __init__(self, text_area):
            self.text_area = text_area

    class StdoutRedirector(IORedirector):
        '''A class for redirecting stdout to this Text widget.'''



    def textPad(self, frame):
        # add a frame and put a text area into it
        textPad = tk.Frame(frame)
        self.text = tk.Text(textPad, height=21, width=68)
        self.text.config()
        # add a vertical scroll bar to the text area
        scroll = tk.Scrollbar(textPad)
        self.text.configure(yscrollcommand=scroll.set,background="black", foreground="green")
        # pack everything
        self.text.pack(side=tk.LEFT, pady=2)
        scroll.pack(side=tk.RIGHT, fill=tk.Y)
        textPad.pack(side=tk.TOP)
        self.text.insert("end", "Begin by selecting log folder..." + "\n")
        self.text.configure(state='disabled') # disable text editing
        sys.stdout = (self) # to begin logging stdio to GUI
        return

    def write(self, txt):
        self.text.configure(state='normal')
        self.text.insert('end', txt)
        self.text.configure(state='disabled')

root = tk.Tk()
root.resizable(width=False, height=False)
center_window(500, 300) # launch in center of screen
app = Application(master=root)
scrollFrame = scrollTxtArea(root)
app.mainloop()
root.destroy()

你们用错了线

第一个:target=需要不带和参数的函数名。 您可以将参数分配给args=它必须是tuple,即使只有一个参数

threading.Thread(target=parselog_v1.main, args=(Src_foldername,) )
现在,您的代码以普通函数的形式运行parselog_v1.main,等待结果,并将此结果作为函数名分配给taget=-因此您有如下内容:

result = parselog_v1.main(Src_foldername)
threading.Thread(target=result)
它停止mainloop,因此无法获取鼠标/键盘事件、刷新窗口等,因此看起来像是窗口冻结

第二:正确创建线程后,必须启动它

my_thread = threading.Thread(target=parselog_v1.main, args=(Src_foldername,) )
my_thread.start()

我们无法在没有parselog_v1的情况下运行它。@furas我做了修改,您的建议很有效。非常感谢。