一个答案,仅供参考。(请记住,我不是Thread
向导。)
如果Thread
没有停止并且您没有取消订阅消息,则有可能从仍在运行的消息中接收消息Thread
,这将尝试更新不再存在的小部件存在。
我已经修改了您的代码以包含Stop
.
在销毁 GUI 之前,我还确保线程已终止。
显然,这只是简单的旋转,您需要确保工作具有检查变量的方法。Thread
join
Thread
Thread
running
线程代码process_csv_class.py
from __future__ import division
from threading import Thread
from pubsub import pub
import os
import glob
import time
########################################################################
class process_csv_thread(Thread):
"""Test Worker Thread Class."""
#----------------------------------------------------------------------
def __init__(self,csv_path,rnti_value):
"""Init Worker Thread Class."""
self.csv_path = csv_path
self.rnti_value = rnti_value
Thread.__init__(self)
self.running = True
self.start() # start the thread i.e. run()
#----------------------------------------------------------------------
def run(self):
all_files_list = glob.glob(self.csv_path+'/*.csv')
output_excel_file='Parsed_output.xlsx'
os.chdir(self.csv_path)
pub.sendMessage("update", msg="Currently loading")
while self.running == True:
time.sleep(1)
pub.sendMessage("update", msg="Processing files")
pub.sendMessage("finish", msg="Thread Stopped")
pub.sendMessage("finish", msg="Processing Terminated")
def stop(self):
self.running = False
主程序:
import time
import wx
import os
import configparser
from pubsub import pub
#from extract_class import TestThread
from process_csv_class import process_csv_thread
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Nokia 5G TTI Parser",size=(560,460))
# Add a panel so it looks the correct on all platforms
self.config = configparser.ConfigParser()
self.config.read("config_setup.ini")
panel = wx.Panel(self, wx.ID_ANY)
self.load_csv_btn=load_csv_btn= wx.Button(panel, label="Load 5G TTI CSV")
load_csv_btn.Bind(wx.EVT_BUTTON, self.selectLogsFolder)
self.def_opening_text = wx.TextCtrl ( panel, size = (122, 17),value = "Default Load Location:",style = wx.TE_READONLY | wx.NO_BORDER | wx.TE_CENTRE )
self.def_opening_location = wx.TextCtrl ( panel, size = (300, -1),value = self.config.get('PrevConfig','defaultLoad') )
self.process_btn=process_btn= wx.Button(panel, label="Process CSV Files")
process_btn.Bind(wx.EVT_BUTTON, self.processCSVs)
self.chart_btn=chart_btn= wx.Button(panel, label="Generate Chart Slides")
chart_btn.Bind(wx.EVT_BUTTON, self.generateSlides)
self.rnti_value = wx.TextCtrl ( panel, size = (45, -1),value = "RNTI:",style = wx.TE_READONLY | wx.NO_BORDER | wx.TE_LEFT )
self.rnti_value_var = wx.TextCtrl(panel,value=self.config.get('PrevConfig','rnti_value_default'))
self.outputMessages = wx.TextCtrl(parent = panel, id = -1, size = (530, 200), style = wx.TE_MULTILINE)
self.load_fold_btn=load_fold_btn= wx.Button(panel, label="Results Folder")
load_fold_btn.Bind(wx.EVT_BUTTON, self.LoadFold)
self.exit_btn=exit_btn= wx.Button(panel, label="Exit")
exit_btn.Bind(wx.EVT_BUTTON, self.onExit)
self.about_btn=about_btn= wx.Button(panel, label="About")
about_btn.Bind(wx.EVT_BUTTON, self.onAbout)
topSizer = wx.BoxSizer(wx.VERTICAL)
load_sizer = wx.BoxSizer(wx.HORIZONTAL)
load_sizer.Add(load_csv_btn, 0, wx.ALL, 5)
load_sizer.Add(self.def_opening_text, 0, wx.ALL, 8)
load_sizer.Add(self.def_opening_location, 0, wx.ALL, 5)
process_csv_sizer = wx.BoxSizer(wx.HORIZONTAL)
process_csv_sizer.Add(process_btn, 0, wx.ALL|wx.EXPAND, 5)
process_csv_sizer.Add(chart_btn, 0, wx.ALL|wx.EXPAND, 5)
rnti_val_sizer = wx.BoxSizer(wx.HORIZONTAL)
rnti_val_sizer.Add(self.rnti_value, 0, wx.ALL|wx.EXPAND, 5)
rnti_val_sizer.Add(self.rnti_value_var, 0, wx.ALL|wx.EXPAND, 5)
display_msg_sizer = wx.BoxSizer(wx.HORIZONTAL)
display_msg_sizer.Add(self.outputMessages, 0, wx.ALL, 5)
exit_row_sizer = wx.BoxSizer(wx.HORIZONTAL)
exit_row_sizer.Add(self.load_fold_btn, 0, wx.ALL, 5)
exit_row_sizer.Add(self.exit_btn, 0, wx.ALL, 5)
exit_row_sizer.Add(self.about_btn, 0, wx.ALL, 5)
topSizer.Add(load_sizer, 0, wx.LEFT)
#topSizer.Add(extract_sizer, 0, wx.RIGHT)
topSizer.Add(process_csv_sizer, 0, wx.RIGHT)
topSizer.Add(rnti_val_sizer, 0, wx.RIGHT)
topSizer.Add(display_msg_sizer, 0, wx.CENTER)
topSizer.Add(exit_row_sizer, 0, wx.RIGHT)
panel.SetSizer(topSizer)
# create a pubsub receiver
pub.subscribe(self.updateDisplay, "update")
pub.subscribe(self.ThreadStopped, "finish")
self.updateDisplay("Please load csv file")
#----------------------------------------------------------------------
def updateDisplay(self, msg):
"""
Receives data from thread and updates the display
"""
self.outputMessages.write("\n>>>%s" % str(msg))
print("\n>>>%s" % str(msg))
#----------------------------------------------------------------------
def ThreadStopped(self, msg):
"""
Receives finish from thread and updates the display
"""
self.outputMessages.write("\n>>>%s" % str(msg))
print("\n>>>%s" % str(msg))
def selectLogsFolder(self, event):
openDirDialog = wx.DirDialog(self,"Choose a directory:",size=(300,400),style=wx.DD_DEFAULT_STYLE)
openDirDialog.SetPath(self.def_opening_location.GetValue())
openDirDialog.ShowModal()
self.csv_folder = openDirDialog.GetPath()
self.updateDisplay("File Location: "+self.csv_folder)
self.def_opening_location.SetValue(self.csv_folder)
openDirDialog.Destroy()
def processCSVs(self, event):
try:
self.pst = process_csv_thread(self.csv_folder,self.rnti_value_var.GetValue())
except:
self.updateDisplay("Error: Please check if CSV File is loaded")
def generateSlides(self, event):
try:
cqi_sinr_thread(self.csv_folder,self.cells_list_input.GetValue(),self.rnti_value_var.GetValue())
except:
self.updateDisplay("Error: Please check if CSV File is loaded")
def LoadFold(self, event):
try:
os.startfile(os.path.dirname(self.csv_folder))
except:
self.updateDisplay("Error: First Load File ")
def onExit(self, event):
try:
self.pst.stop()
self.pst.join()
except:
pass
pub.unsubscribe(self.updateDisplay, "update")
pub.unsubscribe(self.ThreadStopped, "finish")
wx.GetApp().Yield()
time.sleep(4)
#self.config.set('PrevConfig', 'CellsList', self.cells_list_input.GetValue())
self.config.set('PrevConfig', 'rnti_value_default', self.rnti_value_var.GetValue())
self.config.set('PrevConfig', 'defaultLoad', self.def_opening_location.GetValue())
with open('config_setup.ini', 'w') as configfile:
self.config.write(configfile)
configfile.close()
self.Close()
def onAbout(self, event):
info = wx.AboutDialogInfo()
info.Name = "KPI Parser"
info.Version = "v13.0"
info.AddDeveloper("***an \n**nan.**sir@*****.com")
wx.AboutBox(info)
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
config_setup.ini
文件
[PrevConfig]
defaultload = /home/rolf
rnti_value_default = abc