2016-06-13 15 views
0

Ich habe einen Fehler gefunden, der ein Programmbeispiel von "Rapid GUI Programming with Python and Qt" von PyQt4 nach PyQt5 portiert. Das Beispielprogramm demonstriert eine MDI-Anwendung, aus der mehrere Textbearbeitungsfenster innerhalb des Hauptfensters ausgeführt werden können.Portierung von PyQt4 QWorkspace nach PyQt5 QMdiArea - SubWindowList Methode

Ich habe Python 3.4.4 und PyQt 4.8.7 für die PyQt4-Version verwendet. Ich habe Python 3.4.4 und PyQt 5.5.1 für die PyQt5-Version verwendet.

Ich begann mit der Änderung aller alten Signaldefinitionen in neue Stilsignale im ursprünglichen PyQt4-Programm. Neue Stilsignale wurden in PyQt 4.5 implementiert, so dass ich das ursprüngliche Programm mit diesen Änderungen ausführen konnte. Die Anwendung wurde erfolgreich ausgeführt, nachdem alle alten Signale auf neue Signale aktualisiert wurden.

Das ursprüngliche Programm verwendet die PyQt4.QtGui.QWidget.QWorkspace-Klasse, um den MDI-Arbeitsbereich zu implementieren. QWorkspace wurde in PyQt4.3 durch die PyQt5.QtWidgets.QMdiArea Klasse ersetzt. Mein Problem tauchte auf, als ich versuchte, den ursprünglichen Code zu ändern, um mit QMdiArea zu arbeiten.

Jedes Textdokument wird mit einer Instanz eines benutzerdefinierten TextEdit-Widgets, einer Unterklasse von QTextEdit, dargestellt und bearbeitet.

Minimal PyQt5 Version von MDI-Anwendung - texteditor.py

from PyQt5.QtCore import * 
from PyQt5.QtWidgets import * 
from PyQt5.QtGui import * 

class TextEdit(QTextEdit): 
    NextId = 1 

    def __init__(self, filename="", parent=None): 
     print("TextEdit __init__") 
     super(TextEdit, self).__init__(parent) 
     self.setAttribute(Qt.WA_DeleteOnClose) 
     self.filename = filename 
     if not self.filename: 
      self.filename = "Unnamed-{}.txt".format(TextEdit.NextId) 
      TextEdit.NextId += 1 
     self.document().setModified(False) 
     self.setWindowTitle(QFileInfo(self.filename).fileName()) 

    def load(self): 
     print("load - TextEdit") 
     exception = None 
     fh = None 
     try: 
      fh = QFile(self.filename) 
      if not fh.open(QIODevice.ReadOnly): 
       raise IOError(fh.errorString()) 
      stream = QTextStream(fh) 
      stream.setCodec("UTF-8") 
      self.setPlainText(stream.readAll()) 
      self.document().setModified(False) 
     except EnvironmentError as e: 
      exception = e 
     finally: 
      if fh is not None: 
       fh.close() 
      if exception is not None: 
       raise exception 

import sys 
from PyQt5.QtCore import * 
from PyQt5.QtWidgets import * 
from PyQt5.QtGui import * 

__version__ = "1.0.0" 

class MainWindow(QMainWindow): 
    def __init__(self, parent=None): 
     super(MainWindow, self).__init__(parent) 
     self.mdi = QMdiArea() 
     self.setCentralWidget(self.mdi) 
     fileOpenAction = QAction("&Open...", self) 
     fileOpenAction.setShortcut(QKeySequence.Open) 
     fileOpenAction.triggered.connect(self.fileOpen) 
     fileMenu = self.menuBar().addMenu("&File") 
     fileMenu.addAction(fileOpenAction) 
     settings = QSettings() 
     self.restoreGeometry(settings.value("MainWindow/Geometry", 
       QByteArray())) 
     self.restoreState(settings.value("MainWindow/State", 
       QByteArray())) 
     QTimer.singleShot(0, self.loadFiles) 


    def loadFiles(self): 
     if len(sys.argv) > 1: 
      for filename in sys.argv[1:31]: # Load at most 30 files 
       if QFileInfo(filename).isFile(): 
        self.loadFile(filename) 
        QApplication.processEvents() 
     else: 
      settings = QSettings() 
      files = settings.value("CurrentFiles") or [] 
      for filename in files: 
       if QFile.exists(filename): 
        self.loadFile(filename) 
        QApplication.processEvents() #todo What does this do? 

    def fileOpen(self): 
     filename, _ = QFileDialog.getOpenFileName(self, 
       "Text Editor -- Open File") 
     if filename: 
      for textEdit in self.mdi.subWindowList(): 
       print(type(textEdit)) 
       if textEdit.filename == filename: 
        self.mdi.setActiveSubWindow(textEdit) 
        break 
      else: 
       self.loadFile(filename) 

    def loadFile(self, filename): 
     textEdit = TextEdit(filename) 
     try: 
      textEdit.load() 
     except EnvironmentError as e: 
      QMessageBox.warning(self, "Text Editor -- Load Error", 
        "Failed to load {}: {}".format(filename, e)) 
      textEdit.close() 
      del textEdit 
     else: 
      self.mdi.addSubWindow(textEdit) 
      textEdit.show() 

app = QApplication(sys.argv) 
app.setWindowIcon(QIcon(":/icon.png")) 
app.setOrganizationName("Qtrac Ltd.") 
app.setOrganizationDomain("qtrac.eu") 
app.setApplicationName("Text Editor") 
form = MainWindow() 
form.show() 
app.exec_() 

Das Problem in der Fileopen auftritt() -Methode:

PyQt4 Fileopen() -Methode

def fileOpen(self): 
     filename = QFileDialog.getOpenFileName(self, 
       "Text Editor -- Open File") 
     if filename: 
      for textEdit in self.mdi.windowList(): 
       if textEdit.filename == filename: 
        self.mdi.setActiveWindow(textEdit) 
        break 
      else: 
       self.loadFile(filename) 

PyQt5 fileOpen() Methode

def fileOpen(self): 
     filename, _ = QFileDialog.getOpenFileName(self, 
       "Text Editor -- Open File") 
     if filename: 
      for textEdit in self.mdi.subWindowList(): 
       if textEdit.filename == filename: 
        self.mdi.setActiveSubWindow(textEdit) 
        break 
      else: 
       self.loadFile(filename) 

windowList() ist in PyQt5 als subWindowList() implementiert. Das Problem ist, dass in der PyQt4 Version, wenn for textEdit in self.mdi.windowList(): ausgeführt textEdit vom Typ TextEdit ist so die nächste Zeile

if textEdit.filename == filename

arbeitet seit TextEdit einen Dateinamen Parameter hat. und textEdit ist ein {TextEdit} textedit.TextEdit Objekt, aber in der PyQt5 Version, nach for textEdit in self.mdi.subWindowList(): ausgeführt wird, die Art der textEdit ist QMdiSubWindow so, natürlich die Zurückverfolgungs erzeugt:

Traceback (most recent call last): 
    File "texteditor3.py", line 292, in fileOpen 
    if textEdit.filename == filename: 
AttributeError: 'QMdiSubWindow' object has no attribute 'filename' 

Was wirklich verwirrt mich ist, wie textEdit in der PyQt4-Version wird zu einem TextEdit-Typ. Ich würde denken, es wäre ein Str-Typ.

+0

ich ein minimales, vollständig und überprüfbar Beispiel hinzugefügt! –

+0

Um diese Frage angemessen zu halten, habe ich den Minimalcode für die PyQt4-Version nicht eingefügt. Wenn jemand das sehen möchte, würde ich es gerne hinzufügen oder es Ihnen schicken. –

Antwort

0

Ich bin aus Deutschland Ich habe eine Antwort gefunden. Siehe den Code. Sorry über die deutschen Kommentare.

def fileOpen(self): 
    try: 
     # PSc QFileDialog.getOpenFileName gibt ein Tuple zurück 
     # für die weitere Verwendung filname[0] verwenden 
     filename = QFileDialog.getOpenFileName(self, 
       "Text Editor -- Open File") 
     if filename: 
      try: 
       # PSc wenn ein zweites Open durchgeführt wird erhält man die Fehlermeldung 
       # textEdit has no attribute fileName 
       # http://stackoverflow.com/questions/37800036/porting-pyqt4-qworkspace-to-pyqt5-qmdiarea-subwindowlist-method 
       # Lösung scheinbar hier gefunden Zeile 268 269 
       # http://nullege.com/codes/show/src%40p%40y%40pyqt5-HEAD%40examples%40mainwindows%40mdi%40mdi.py/168/PyQt5.QtWidgets.QMdiArea.subWindowActivated.connect/python 
       # Folgende Zeile dementsprechen geändert 
       # for textEdit in self.mdi.subWindowList(): 
       for windows in self.mdi.subWindowList(): 
        textEdit = windows.widget() 
        print('In File Open textEdit.filename: ' + textEdit.filename) 
        if textEdit.filename == filename[0]: 
         self.mdi.setActiveWindow(textEdit) 
         break 
       else: 
        # PSc filename Tuple daher filename[0] übergeben 
        self.loadFile(filename[0]) 
      except: 
       e = sys.exc_info() 
       print('An exception occurred in def fileOpen if Filename : \n' + str(e) + '\n') 
    except: 
     e = sys.exc_info() 
     print('An exception occurred in def fileOpenin: \n' + str(e) + '\n') 

Ich habe es everywher wie geändert:

def fileSave(self): 
    try: 
     # PSc PyQt4 Syntax 
     # textEdit = self.mdi.activeSubWindow() 
     # geändert laut Zeile 268,269 
     # nullege.com/codes/show/src%40p%40y%40pyqt5-HEAD%40examples%40mainwindows%40mdi%40mdi.py/168/PyQt5.QtWidgets.QMdiArea.subWindowActivated.connect/python 
     window = self.mdi.activeSubWindow() 
     textEdit = window.widget() 
     if textEdit is None or not isinstance(textEdit, QTextEdit): 
      return True 
     try: 
      textEdit.save() 
      return True 
     except EnvironmentError as e: 
      QMessageBox.warning(self, "Text Editor -- Save Error", 
        "Failed to save {}: {}".format(textEdit.filename, e)) 
      return False 
    except Exception as error: 
     print('An exception occurred in fileSave: {}'.format(error)) 
+1

Sie könnten Ihre Antwort erklären, um die Qualität zu verbessern. – eyllanesc

+0

Vielen Dank für die Antwort. Leider ist es neun Monate her, seit ich diese Frage gestellt habe und ich bin jetzt sehr beschäftigt mit anderen Dingen. Ich werde meine Frage überprüfen und dann Ihre Lösung versuchen. Ich kann mich ein paar Tage oder Wochen dauern, bevor ich Zeit habe. –