我在使用 Tkinter(ttk 模块)并在后台运行函数并将函数的print
( sys.stdout
) 消息接收到 GUI 文本小部件时遇到了严重问题self.constext
。该函数本身包含执行空间查询的类,大约需要 15 分钟,其间有打印语句来检查计算状态。在编辑这篇文章之前,我确实尝试过线程,实现 ThreadingClient 或 QueueClient 的队列,但启动 GUI 总是导致程序崩溃
所以,这是我到目前为止的代码
import tkFileDialog
import tkMessageBox
import ttk
import Tkinter
import Queue
import os
import time
import sys
import threading
import multiprocessing
import gemeindesteckbrief__SupportTools__
class SystemInfoSupport():
#def __init__(self, master,factshHW, factshHwGeb,factshHwSch, factshGem,
factshGeol, factshWLV) :
def __init__(self,master):
#Actual Window
self.sysInf =ttk.Frame (master)
self.sysInf.grid()
self.sysInf.grab_set()
self.incrVal = 0
#self.__calcFacthw = factshHW
#self.__calcFacthwGeb = factshHwGeb
#self.__calcFactHwSch = factshHwSch
#self.__calcFactGeol = factshGeol
#self.__calcFactWLV = factshWLV
#self.__calcFactGem = factshGem
#print self.__calcFacthwGeb
self.style= ttk.Style()
self.style.configure("Head.TLabel",foreground="#20B2AA", background="#E6E6FA", font = "Verdana 12 bold")
self.headLabel= ttk.Label (self.sysInf,text = "Systeminformation- Kalkulation",style = "Head.TLabel")
self.headLabel.grid(row=0, column =0, sticky ="NW",pady = 15, padx =20)
#Process OVerview
self.mainFrame = ttk.LabelFrame (self.sysInf,width=200,height=100)
self.mainFrame.grid(row=2, column =0, sticky = "NW", padx = 15, pady = 5)
self.style.configure("Prog.TLabel", font = "Verdana 10 italic underline")
self.progLabel= ttk.Label (self.mainFrame,text = "Räumliche Analysen-Fortschritt:", style ="Prog.TLabel")
self.progLabel.grid (row =2,column =1, sticky = "NW", padx = 10, pady = 2)
self.progBar= ttk.Progressbar(self.mainFrame,mode='determinate',length = 370, name='progBar1')
self.progBar.grid(row=3, column=0, columnspan=4,sticky ="NW", pady=5, padx=10)
self.style.configure("Scale.TLabel", font = "Verdana 8 bold")
self.scaleBounds = ttk.Label (self.mainFrame,text = "0 %\t\t\t\t\t 100 %")
self.scaleBounds.grid (row =4,column =1, sticky = "NW", padx = 5, pady = 1)
self.textFrame = ttk.LabelFrame (self.mainFrame,width=200,height=100)
self.textFrame.grid(row=5, column =1, sticky = "NW", padx = 5, pady = 10)
self.style.configure("Consol.TLabel", font ="Verdana 8 bold")
self.consLable = ttk.Label (self.textFrame,text = "Log-Console:",style ="Consol.TLabel")
self.consLable.grid (row =6,column =1, sticky = "NW", padx = 5, pady = 1)
self.consText= ttk.Tkinter.Text(self.textFrame, wrap = "word")
self.consText.grid(row =7,column =1, rowspan =4)
self.consText.tag_configure("stderr", foreground="#b22222")
self.scrollText= ttk.Scrollbar(self.textFrame,command = self.consText.yview)
self.scrollText.grid(row =7,column =2,rowspan =4,sticky='NSEW')
self.consText.config(yscrollcommand = self.scrollText.set)
self.cancelButton = ttk.Button (self.mainFrame, text ="Abbrechen",command = self.testProgBar)
self.cancelButton.grid (row =12,column =1)
sys.stdout = TextRedirector(self.consText, "stdout")
sys.stderr= TextRedirector(self.consText, "stderr")
# Create new threads
# run function in background using a ThreadingClient
# self.thread1 = gemeindesteckbrief_SpatialThread.SpatialThread(self.__calcFacthw, self.__calcFacthwGeb)
#run function in a threading.Thread
#self.thread1 = threading.Thread(name ="MyThread", target = self.prozessCalculateFactsheets)
#run function in a threading.Timer
#self.thread1= threading.Timer(2,self.calculateFactsheets)
#Start the thread
#self.thread1.start()
#self.check_thread()
#Check if thread is still executing or not
def check_thread(self):
# Still alive? Check again in half a second
if self.thread1.isAlive():
self.sysInf.after(500,self.check_thread)
# function to test the sys.stdout behaviour and writting to the Tkinter.text widget
def testProgBar (self):
print "hello my friend"
sys.stderr.write("hello my error friend\n")
self.sysInf.grab_release()
# the actual function needed to be executed in background
def calculateFactsheets (self):
# Read the directory to the input data of the init_File and add to a new Factsheet spatial calculation
try:
print "''''Hello from the Calculation Function ()''''"
requireData = gemeindesteckbrief__SupportTools__.ToolSet()
if self.__calcFacthw == 1:
factsheetHochw = gemeindesteckbrief_SpatialCalculFactshHochw.SpatialAnalysis_FactsheetHochwasser(requireData.readData(13),requireData.readData(10),
requireData.readData(20), requireData.readData(21), requireData.readData(22), requireData.readData(23), requireData.readData(24),
requireData.readData(25), requireData.readData(26))
factsheetHochw.verkExpertAnalyseGZPBWV()
factsheetHochw.verkExpertAnalyseHSG()
factsheetHochw.verkExpertAnalyseTotal()
factsheetHochw.verkExpertAnalyseGZPOI()
factsheetHochw.verkExpertAnalyseGZLOI()
factsheetHochw.verkExpertAnalyseHSGPOI()
factsheetHochw.verkExpertAnalysePLOITot()
factsheetHochw.verkExpertAnalyseLandWald()
factsheetHochw.verkExpertAnalyseLandWaldTotal()
if self.__calcFacthwGeb == 1:
print "FACTSHEET HOCHWASSER Gebaeude startet"
factsheetHochwGeb = gemeindesteckbrief_SpatialCalculFactshHochwGebaeude.SpatialAnalysis_FactsheetHochwGebaeude(requireData.readData(13),requireData.readData(10),
requireData.readData(16),requireData.readData(15), requireData.readData(17),requireData.readData(18))
print "Data correct initialized"
factsheetHochwGeb.gebaeudeExpAnalyseGZPBWV()
factsheetHochwGeb.gebaeudeExpAnalyseHSG()
factsheetHochwGeb.gebaeudeExpAnalyseTotal()
tkMessageBox.showinfo("Räumlicher-Analyse Erfolgreich","Die Berechnungen wurden erfolgreich abgeschlossen!")
except:
tkMessageBox.showerror ("FactsheetHochwasser_Gebaeude FEHLER","Bei der Berechnung ist ein Fehler aufgetreten!\n Für Details öffnen Sie das Error-File in der Programmumgebung")
class TextRedirector(object):
def __init__(self,widget, tag):
self.targetwidget = widget
self.targettag = tag
#@Override the sys.stdout & sys.stderr methods to write to the text widget instead of the python console
def write(self, str):
self.targetwidget.configure(state="normal")
self.targetwidget.insert("end", str, (self.targettag,))
self.targetwidget.configure(state="disabled")
root = ttk.Tkinter.Tk()
root.title ("SystemINFO-Menü")
runGUI = SystemInfoSupport (root)
root.mainloop ()
基本上我需要def calculateFactsheets (self):
在后台执行该功能并接收打印或错误控制台消息以将它们写入小部件。
有任何想法吗??