在PyQt中刷新QTextEdit
我正在写一个PyQt应用程序,它会在一个小部件中接收一些输入,然后处理一些文本文件。
目前的情况是,当用户点击“处理”按钮时,会弹出一个新窗口,里面有一个QTextEdit,用来输出一些日志信息。
在Mac OS X上,这个窗口会自动刷新,你可以看到处理的进度。
但是在Windows上,这个窗口会显示(未响应),然后等所有处理完成后,日志输出才会显示出来。我猜我需要在每次写入日志后刷新窗口,我也试着用定时器之类的方法,但一直没能成功。
下面是源代码。它有两个文件,一个是GUI.py,负责所有的界面部分,另一个是MOVtoMXF,负责所有的处理。
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"
还有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()
如果需要其他代码(我觉得这些代码应该够了),请告诉我。
任何帮助都非常感谢。
马克
1 个回答
1
看起来你正在运行一个外部程序,并把它的输出捕捉到一个QTextEdit里。我没有看到Form.process
的代码,但我猜在Windows上,你的函数是等外部程序完成后,才快速把所有内容扔到QTextEdit
里。
如果你的界面确实是在等另一个进程完成,那就会像你描述的那样卡住。你需要看看subprocess,或者甚至是popen,这样可以以“非阻塞”的方式获取程序的输出。
避免出现“(未响应)”的关键是每隔几秒调用几次QApplication.processEvents
。在这种情况下,QTimer
是没用的,因为如果Qt无法处理它的事件,就无法调用任何信号处理函数。