2009-08-21 9 views
2

Im écrire une application PyQt qui prend une entrée dans un widget, puis traite certains fichiers texte.Actualiser QTextEdit dans PyQt

En ce moment, lorsque l'utilisateur clique sur le bouton "traiter", une fenêtre séparée avec un QTextEdit apparaît et affiche des messages de journalisation.

Sous Mac OS X, cette fenêtre est actualisée automatiquement et vous pouvez voir le processus.

Sous Windows, la fenêtre signale (ne répond pas) et une fois que tout le processus est terminé, la sortie du journal est affichée. Je suppose que j'ai besoin de rafraîchir la fenêtre après chaque écriture dans le journal, et j'ai regardé autour d'utiliser une minuterie. etc, mais a eu beaucoup de chance pour le faire fonctionner.

Ci-dessous le code source. Il a deux fichiers, GUI.py qui fait toutes les choses de l'interface graphique et MOVtoMXF qui fait tout le traitement.

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" 

ET 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() 

Si un autre code est nécessaire (je pense que c'est tout ce qui est nécessaire), puis me le faire savoir.

Toute aide serait géniale.

Mark

Répondre

1

On dirait que vous êtes en cours d'exécution d'un programme externe, capturant sa sortie dans un QTextEdit. Je n'ai pas vu le code de Form.process, mais je devine sur Windows votre fonction attend la fin du programme externe, puis rapidement tout dumper au QTextEdit.

Si votre interface attend vraiment que l'autre processus se termine, il se bloque de la manière que vous décrivez. Vous aurez besoin de regarder sous-processus ou peut-être même popen pour obtenir la sortie du programme d'une manière "non bloquante". La clé pour éviter "(Ne répond pas)" est d'appeler QApplication.processEvents quelques fois toutes les quelques secondes. Le QTimer ne va pas aider dans ce cas, car si Qt ne peut pas traiter ses événements, il ne peut appeler aucun gestionnaire de signal.

+0

J'ai ajouté un peu plus de code pour que vous puissiez voir l'événement de processus. Pour autant que je sache, c'est juste l'initialisation d'une classe. –

+0

Il semble donc que vous capturez 'sys.stdout' pendant que vous exécutez une grande fonction Python. La meilleure chose à faire est d'appeler 'qg.QApplication.processEvents()' à la fin de votre méthode 'OutLog.write'. Ensuite, l'interface aura une chance de se mettre à jour chaque fois que quelque chose s'imprime sur stdout. –