Update QTextEdit in PyQt
I'm writing a PyQt application that takes some input in one widget and then processes some text files.
The moment the user clicks the "process" button, a separate window with a QTextEdit popup appears and gives some registration messages.
On Mac OS X, this window refreshes automatically and you see the progress.
On Windows, window reports (Not Responding) and then, once all processing is done, the log output will be shown. I guess I need to update the window after every log entry, and ive looked around for timer usage. etc, but havnt lucky it works.
Below is the source code. It has two files: GUI.py, which does all the GUI functionality, and MOVtoMXF, which does all the processing.
GUI.py
import os
import sys
import MOVtoMXF
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Form(QDialog):
def process(self):
path = str(self.pathBox.displayText())
if(path == ''):
QMessageBox.warning(self, "Empty Path", "You didnt fill something out.")
return
xmlFile = str(self.xmlFileBox.displayText())
if(xmlFile == ''):
QMessageBox.warning(self, "No XML file", "You didnt fill something.")
return
outFileName = str(self.outfileNameBox.displayText())
if(outFileName == ''):
QMessageBox.warning(self, "No Output File", "You didnt do something")
return
print path + " " + xmlFile + " " + outFileName
mov1 = MOVtoMXF.MOVtoMXF(path, xmlFile, outFileName, self.log)
self.log.show()
rc = mov1.ScanFile()
if( rc < 0):
print "something happened"
#self.done(0)
def __init__(self, parent=None):
super(Form, self).__init__(parent)
self.log = Log()
self.pathLabel = QLabel("P2 Path:")
self.pathBox = QLineEdit("")
self.pathBrowseB = QPushButton("Browse")
self.pathLayout = QHBoxLayout()
self.pathLayout.addStretch()
self.pathLayout.addWidget(self.pathLabel)
self.pathLayout.addWidget(self.pathBox)
self.pathLayout.addWidget(self.pathBrowseB)
self.xmlLabel = QLabel("FCP XML File:")
self.xmlFileBox = QLineEdit("")
self.xmlFileBrowseB = QPushButton("Browse")
self.xmlLayout = QHBoxLayout()
self.xmlLayout.addStretch()
self.xmlLayout.addWidget(self.xmlLabel)
self.xmlLayout.addWidget(self.xmlFileBox)
self.xmlLayout.addWidget(self.xmlFileBrowseB)
self.outFileLabel = QLabel("Save to:")
self.outfileNameBox = QLineEdit("")
self.outputFileBrowseB = QPushButton("Browse")
self.outputLayout = QHBoxLayout()
self.outputLayout.addStretch()
self.outputLayout.addWidget(self.outFileLabel)
self.outputLayout.addWidget(self.outfileNameBox)
self.outputLayout.addWidget(self.outputFileBrowseB)
self.exitButton = QPushButton("Exit")
self.processButton = QPushButton("Process")
self.buttonLayout = QHBoxLayout()
#self.buttonLayout.addStretch()
self.buttonLayout.addWidget(self.exitButton)
self.buttonLayout.addWidget(self.processButton)
self.layout = QVBoxLayout()
self.layout.addLayout(self.pathLayout)
self.layout.addLayout(self.xmlLayout)
self.layout.addLayout(self.outputLayout)
self.layout.addLayout(self.buttonLayout)
self.setLayout(self.layout)
self.pathBox.setFocus()
self.setWindowTitle("MOVtoMXF")
self.connect(self.processButton, SIGNAL("clicked()"), self.process)
self.connect(self.exitButton, SIGNAL("clicked()"), self, SLOT("reject()"))
self.ConnectButtons()
class Log(QTextEdit):
def __init__(self, parent=None):
super(Log, self).__init__(parent)
self.timer = QTimer()
self.connect(self.timer, SIGNAL("timeout()"), self.updateText())
self.timer.start(2000)
def updateText(self):
print "update Called"
And MOVtoMXF.py
import os
import sys
import time
import string
import FileUtils
import shutil
import re
class MOVtoMXF:
#Class to do the MOVtoMXF stuff.
def __init__(self, path, xmlFile, outputFile, edit):
self.MXFdict = {}
self.MOVDict = {}
self.path = path
self.xmlFile = xmlFile
self.outputFile = outputFile
self.outputDirectory = outputFile.rsplit('/',1)
self.outputDirectory = self.outputDirectory[0]
sys.stdout = OutLog( edit, sys.stdout)
class OutLog():
def __init__(self, edit, out=None, color=None):
"""(edit, out=None, color=None) -> can write stdout, stderr to a
QTextEdit.
edit = QTextEdit
out = alternate stream ( can be the original sys.stdout )
color = alternate color (i.e. color stderr a different color)
"""
self.edit = edit
self.out = None
self.color = color
def write(self, m):
if self.color:
tc = self.edit.textColor()
self.edit.setTextColor(self.color)
#self.edit.moveCursor(QtGui.QTextCursor.End)
self.edit.insertPlainText( m )
if self.color:
self.edit.setTextColor(tc)
if self.out:
self.out.write(m)
self.edit.show()
If any other code is required (I think that's all it needs), just let me know.
Any help would be great.
Mark
source to share
It looks like you are running an external program by capturing its output into a QTextEdit. I haven't seen the code Form.process
, but my guess is that on windows your function waits for the external program to complete and then quickly resets everything to QTextEdit
.
If your frontend is indeed waiting for another process to complete, it will hang as you describe. You will need to look at the subprocess, or perhaps even popen, to get out of the program in a "non-blocking" way.
The key to avoiding "(not responding)" is to call QApplication.processEvents
several times every few seconds. QTimer
will not help in this case, because if Qt cannot handle its events, it cannot call any signal handlers.
source to share