简体   繁体   English

Tkinter窗口甚至不响应线程

[英]Tkinter window does not respond even with threading

I'm building a simple GUI with TKinter in Python. 我正在Python中使用TKinter构建一个简单的GUI。 I have a browse button that browses files on a computer and open the selected file. 我有一个浏览按钮,可浏览计算机上的文件并打开所选文件。 When the file is selected a function called to open the file and start reading it. 选择文件后,将调用一个函数来打开文件并开始读取文件。 However, after I click the button, the window doesn't respond anymore. 但是,单击按钮后,窗口不再响应。 When I searched I found that this is because TKinter is single threaded, and the main gui thread may get stuck with some tasks, but even after I've used some simple threading the window still freezes. 当我搜索时,发现这是因为TKinter是单线程的,并且主gui线程可能会卡在某些任务上,但是即使在我使用了一些简单的线程之后,窗口仍然冻结。

Here is a sample code of what I'm doing, 这是我正在做的示例代码,

   import threading


from Tkinter import *
from PyQt4 import *
from tkFileDialog import askopenfilename
import numpy as np
import xlrd

global columnList

def open_file (file_name):
    #fileName=input ("Enter file name (example.dat)")
    #colCount= input ("Enter number of columns in the file")

    try:
        workbook = xlrd.open_workbook(file_name)
        sheet=workbook.sheet_by_index(0)
        columns = []
        for i in range (0,sheet.ncols-1):
           columns.append(np.array (sheet.col_values(i,1))) # make a list, each index has a numpy array that represnts a column.
           if (i!=0):
               columns[i]= columns[i].astype(np.float)
        #Preprocessing depth:
        m= columns [0]
        for i in range (m.shape[0]):
            m[i]= m[i]*2 +1

        m=m.astype(np.int)
        columns[0]=m

        print( sheet.row_values(0,sheet.ncols) )
        # removing nans:
        index=input("enter the column index to interpolate: ")
        m= columns [index]
        for i in range (m.shape[0]-1, -1, -1):
            if (np.isnan(m[i])):
                m=np.delete(m,i)
                columns[0]=np.delete(columns[0],i)
                columns [index]= np.delete(columns[index],i)

    except IOError:
        print ("The specified file was not found")

    return columns [0], columns [index]


class Interface:
    def __init__(self, master):
        #frame= Frame (master)
        #frame.grid (sticky=Y)

        self.title= Label(master,text="Kriging Missing data Imputation", fg="blue", font=("Helvetica", 18))
        self.select_file= Label (master, text="Select the file that contains the data (must be an excel file): ", font=("Helvetica", 12))


        self.title.grid (row=1, column=5, columnspan= 4, pady= (20,0))
        self.select_file.grid (row=3, column=1, sticky=W, pady=(20,0), padx=(5,2))
        self.browse_button= Button (master, text="Browse", command=self.browser, font=("Helvetica", 12), width=12)
        self.browse_button.grid (row=3, column=3, pady=(20,0))

        self.varColumn= StringVar(master)
        self.varColumn.set("depth")
        self.columnLabel= Label(master,text="Select a column to process", font=("Helvetica", 12))

        self.columnList= OptionMenu (master, self.varColumn,"nan", "?", "*")

        self.columnLabel.grid (row=5, column=1, pady=(20,0), sticky=W, padx=(5,0))
        self.columnList.grid(row=5, column= 3, pady= (20,0))


        self.missing_label= Label(master, text="Select missing data indicator: ", font=("Helvetica", 12))
        self.var = StringVar (master)
        self.var.set("nan")
        self.menu= OptionMenu (master, self.var,"nan", "?", "*")

        self.missing_label.grid (row=7, column=1, padx=(5,2), pady= (20,0), sticky=W)
        self.menu.grid(row=7, column=3, pady= (20,0))

        self.extrapolate= Label (master, text="Select a range for extrapolation (max=800): ", font=("Helvetica", 12))
        self.max_extra= Entry (master)

        self.extrapolate.grid (row=9, column=1, padx=(5,2), pady= (20,0),  sticky=W)
        self.max_extra.grid (row=9, column=3, pady=(20,0))

        self.a_label= Label (master, text="enter the value of a (range): ", font=("Helvetica", 12))
        self.a_value= Entry (master)

        self.a_label.grid (row=11, column=1, padx=(5,2), pady=(20,0),  sticky=W)
        self.a_value.grid (row=11, column=3,  pady=(20,0))


        self.start_button= Button (master, text="Start", font=("Helvetica", 12), width=12)
        self.pause_button= Button (master, text= "Pause", font=("Helvetica", 12),width=12)
        self.stop_button= Button (master, text="stop", font=("Helvetica", 12),width=12)

        self.start_button.grid (row=13, column=1, pady=(30,0) )
        self.pause_button.grid (row=13, column=2, pady=(30,0))
        self.stop_button.grid (row=13, column=3, pady=(30,0))



    def browser (self):
        filename = askopenfilename()
        x,v= threading.Thread (target=open_file(filename))
        #open_file(filename)
        # we must then send the file name to the function that  reads it somehow.

window= Tk () #main window.
starter= Interface (window)


window.mainloop() #keep the window open until the user decides to close it.

I've read that Tkinter is not thread safe, and I maybe using some threading in some other functions, so how can I solve the problem of freezing with using threading? 我读过Tkinter不是线程安全的,也许我在其他一些函数中使用了线程,那么如何解决使用线程冻结的问题呢? Or, shall I use another GUI builder like PyQt4? 或者,我应该使用其他PyQt4这样的GUI构建器吗?

Any help is appreciated. 任何帮助表示赞赏。

Thanks. 谢谢。

You don't use a thread. 您不使用线程。 You are calling open_file and try to start with its return-value a new thread. 您正在调用open_file并尝试以其返回值开始一个新线程。 You have to use the function as an argument, and not call it: 您必须将函数用作参数,而不要调用它:

th = threading.Thread(target=open_file, args=(filename,))
th.start()

The next point is, that threads have no return value. 接下来的一点是,线程没有返回值。 When the thread finished, your browser -function has finished long before. 线程完成后,您的browser功能已在很久之前完成。 So you cannot get the return values x and v . 因此,您无法获得返回值xv If you want to communicate between threads and GUI you have to use queues and a separate event loop with, which checks the queue and calls itself again with after . 如果要在线程和GUI之间进行通信,则必须使用队列和单独的事件循环,该事件循环将检查队列并使用after再次调用自身。

Even Qt is not thread-safe in the way, that some thread can change the GUI. 即使Qt也不是线程安全的,有些线程可以更改GUI。 But it has the signal-slot-concept, which replaces queues for communication in a much more convenient way. 但是它具有信号时隙概念,可以以更方便的方式替换队列进行通信。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM