【发布时间】:2015-07-06 08:31:48
【问题描述】:
我正在用 python 编写一个程序,它将处理从某个 excel 文件中读取的大量数据。我已经使用 Tkinter 为这个程序构建了一个 GUI。我知道 Tkinter 是单线程的,因此为了打开文件并进行一些进程,我使用了一个线程来不阻塞 GUI。线程任务之一是填充一个列表(在我的代码中称为 columnList)并将其元素用作选项菜单中的选项,因此在线程完成之前选项菜单为空,因此我使用 join () 让主线程等待工作线程。而且,问题来了,只要工作线程在执行 GUI 就不会响应(大约 7 秒),但之后它会正常工作。
我想使用一些图形指示器来指示正在加载的内容,同时阻止 GUI 窗口,使用户无法单击它。线程停止后,指示器应消失,GUI 应再次启用。我搜索了这样一个概念,但是在网上没有找到这样的东西,这里的这个问题,Python Tkinter: loading screen和我的情况很相似,但是没有答案。
这是我需要应用该概念的代码的一部分:
__author__ = 'Dania'
import threading
from Tkinter import *
from tkFileDialog import askopenfilename
import numpy as np
import xlrd
global x
global v
x = np.ones(5)
v= np.ones(5)
global columnList
columnList=""
def open_file (file_name):
try:
workbook = xlrd.open_workbook(file_name)
sheet=workbook.sheet_by_index(0)
global columns
columns = [] #this is a list, in each index we will store a numpy array of a column values.
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. 1 means start from row 1 (leave the label)
if (i!=0):
columns[i]= columns[i].astype(np.float)
#Preprocessing columns[0]:
m= columns [0]
for i in range (m.shape[0]):
m[i]= m[i]*2 +1
m=m.astype(np.int)
columns[0]=m
global columnList
columnList= np.array(sheet.row_values(0)) #I was using sheet.row(0), but this is better since it doesn't return a 'u'
columnList=columnList.astype(np.str)
# removing nans:
index=input("enter the column index to interpolate: ") #this should be user input
n= columns [index]
for i in range (n.shape[0]-1, -1, -1):
if (np.isnan(n[i])):
n=np.delete(n,i)
columns[0]=np.delete(columns[0],i)
columns [index]= np.delete(columns[index],i)
except IOError:
print ("The specified file was not found")
global x
np.resize(x, m.shape[0])
x=columns[0]
global v
np.resize(v,n.shape[0])
v=columns[index]
#return columns [0], columns [index]
class Interface:
def __init__(self, master):
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.varLoc= StringVar(master)
self.varLoc.set("status")
self.varColumn= StringVar(master)
self.varColumn.set("")
self.locationColumn= Label(master,text="Select a column as a location indicator", font=("Helvetica", 12))
self.columnLabel= Label(master,text="Select a column to process", font=("Helvetica", 12))
global locationOption
global columnOption
columnOption= OptionMenu (master, self.varColumn,"",*columnList)
locationOption= OptionMenu (master, self.varLoc,"",*columnList)
self.locationColumn.grid (row=5, column=1, pady=(20,0), sticky=W, padx=(5,0))
locationOption.grid (row=5, column=3, pady=(20,0))
self.columnLabel.grid (row=7, column=1, pady=(20,0), sticky=W, padx=(5,0))
columnOption.grid(row=7, 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=9, column=1, padx=(5,2), pady= (20,0), sticky=W)
self.menu.grid(row=9, 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=11, column=1, padx=(5,2), pady= (20,0), sticky=W)
self.max_extra.grid (row=11, 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=13, column=1, padx=(5,2), pady=(20,0), sticky=W)
self.a_value.grid (row=13, 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=15, column=1, pady=(30,0) )
self.pause_button.grid (row=15, column=2, pady=(30,0))
self.stop_button.grid (row=15, column=3, pady=(30,0))
def browser (self):
filename = askopenfilename()
#indicator should start here.
t=threading.Thread (target=open_file, args=(filename, ))
t.start()
t.join() #I use join because if I didn't,next lines will execute before open_file is completed, this will make columnList empty and the code will not execute.
#indicator should end here.
opt=columnOption.children ['menu']
optLoc= locationOption.children ['menu']
optLoc.entryconfig (0,label= columnList [0], command=self.justamethod)
opt.entryconfig (0, label= columnList [0], command=self.justamethod)
for i in range(1,len (columnList)):
opt.add_command (label=columnList[i], command=self.justamethod)
optLoc.add_command (label=columnList[i], command=self.justamethod)
def justamethod (self):
print("method is called")
print(self.varLoc.get())
window= Tk () #main window.
starter= Interface (window)
window.mainloop() #keep the window open until the user decides to close it.
我尝试在方法浏览器中添加一些进度条,像这样,
def browser (self):
filename = askopenfilename()
progressbar = ttk.Progressbar(orient=HORIZONTAL, length=200, mode='determinate')
progressbar.pack(side="bottom")
progressbar.start()
t=threading.Thread (target=open_file, args=(filename, ))
t.start()
t.join() #I use join because if I didn't,next lines will execute before open_file is completed, this will make columnList empty and the code will not execute.
progressbar.stop()
opt=columnOption.children ['menu']
opt.entryconfig (0, label= columnList [0], command=self.justamethod)
for i in range(1,len (columnList)):
opt.add_command (label=columnList[i], command=self.justamethod)
optLoc.add_command (label=columnList[i], command=self.justamethod)
def justamethod (self):
print("method is called")
window= Tk () #main window.
starter= Interface (window)
window.mainloop() #keep the window open until the user decides to close it.
但是,上面的代码甚至没有显示进度条,这不是我真正需要的。
编辑:编辑代码时固定空格。一个工作代码示例是第一个代码 sn-p 中的示例。
谁能告诉我怎么做?
感谢任何帮助。
谢谢。
【问题讨论】:
-
能否请您修复缩进,因为 Python 中的缩进很重要?
-
@Christopher Wallace 是的,实际上我没有放所有代码,因此缩进组织得不好,我将编辑问题。谢谢
-
@Christopher Wallace 我编辑了问题
-
嗨,达尼亚!我希望能够提供帮助,但我不确定我能不能。无论如何,不是要破坏你,但你应该提供一个工作示例,这意味着我们可以运行和测试一些代码。所以你应该包括
imports等。例如,我在运行你的代码时遇到了这个错误:NameError: name 'columnList' is not defined。如果你这样做,我会开一个赏金,以便其他人可以更多地关注这个帖子;) -
谢谢 :),第一个代码 sn-p 是一个 woking 示例,请检查它。
标签: python multithreading user-interface tkinter progress-bar