У меня серьезная проблема с использованием Tkinter (модуль ttk) и запуском функции в фоновом режиме и получением print(sys.stdout) сообщений функции в текстовый виджет GUIself.constext. Сама функция содержит классы, которые выполняют пространственные запросы, занимающие около 15 минут, а между ними есть операторы печати для проверки состояния расчета. Пока этот пост не был отредактирован, я пробовал использовать threading, Queue, реализуя ThreadingClient или QueueClient, но запуск графического интерфейса всегда приводил к сбою программы.
Итак, вот мой код до сих пор
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): в фоновом режиме и получить сообщения консоли печати или ошибки, чтобы записать их в виджет.
Любые идеи??