2016-06-12 24 views
2

Ich bin das Tutorial auf einem license wizard (mit PyQt5) versuchen zu lernen, wie man nicht-lineare Assistenten erstellen. Allerdings scheint ich bei einem Problem stecken zu bleiben.Dynamisch hinzufügen/entfernen Fertig stellen von QWizardPage basierend auf Änderung in seinem Inhalt

Ich möchte eine Seite mit einer QComboBox haben, wo das ausgewählte Element bestimmt, ob die aktuelle QWizardPage, die die Combobox enthält, die letzte Seite ist oder nicht.

Hier ist, was die Seite bisher enthält:

class CalibrationPageSource(QWizardPage): 
    def __init__(self, parent): 
     super(CalibrationPageSource, self).__init__(parent) 
     self.setTitle('Calibration Wizard') 
     self.setSubTitle('Select the source for the calibration') 

     layout = QVBoxLayout() 
     label = QLabel(''' 
      <ul> 
       <li><b>From calibration file</b>: browse and select an existing YAML calibration file that contains the camera matrix and distortion coefficients (for example from a previous calibration)</li> 
       <li><b>From image files</b>: browse and select one or more image files with the calibration pattern visible inside each</li> 
       <li><b>From stream</b> - if the calibration node is connected to an active <b><i>Device node</i></b> you can use its image stream to interactively calibrate your device</li> 
      </ul> 
     ''') 
     label.setWordWrap(True) 
     layout.addWidget(label) 

     layout_sources = QHBoxLayout() 
     label_sources = QLabel('Source:') 
     self.selection_sources = QComboBox() 
     self.selection_sources.addItem('Calibration file') 
     self.selection_sources.addItem('Image files') 
     self.selection_sources.addItem('Stream') 
     self.selection_sources.currentIndexChanged['QString'].connect(self.source_changed) 
     self.selection_sources.setCurrentIndex(1) 
     layout_sources.addWidget(label_sources) 
     layout_sources.addWidget(self.selection_sources) 
     layout.addLayout(layout_sources) 

     self.setLayout(layout) 

    @pyqtSlot(str) 
    def source_changed(self, source): 
     if source == 'Calibration file': 
      self.setFinalPage(True) 
      # TODO Add file dialog 
     else: 
      self.setFinalPage(False) 
      # TODO Remove file dialog (if present) 

Wenn self.selection_sources ‚s aktuelle Elemente Änderungen an Calibration file Ich mag würde den Rest des Assistenten überspringen, dass die Seite endgültig machen. In diesem Fall möchte ich die Next Schaltfläche entfernen. In allen anderen Fällen (derzeit nur zwei: Image files und Stream) möchte ich, dass der Assistent normal arbeitet, das ist nicht als eine letzte Seite.

Ich habe versucht, einen benutzerdefinierten isComplete(...) aber das Problem ist, dass es die Umsetzung sowohl Next und Finish deaktiviert, wenn Calibration file ausgewählt ist. Ich kann mit einer deaktivierten Next Taste leben (anstatt es vollständig zu verstecken), aber eine deaktivierte Finish macht grundsätzlich in meinem Fall keinen Sinn. Ich bin wirklich überrascht, dass die Next Schaltfläche vorhanden ist. Soll es nicht komplett verschwinden, wenn eine letzte Seite erreicht ist?

Irgendwelche Ideen, wie man dieses Problem löst? Ich dachte über das Durchlaufen der Elemente in der QWizardPage und manuell Deaktivieren/Verbergen der Next-Schaltfläche, aber ich hoffe, dass es eine einfachere, Out-of-the-Box-Möglichkeit, das zu tun. Im aktuellen Zustand funktioniert die dynamische Einfügung von Finish aber aufgrund der Next Schaltfläche die Übergänge des Wizards sind nicht richtig eingestellt.

Antwort

0

In Ihrem Code verwenden Sie bereits QWizardPage.setFinalPage(True), um eine Zwischenschaltfläche zu einer Zwischenseite hinzuzufügen. Jetzt ist der nächste Button noch vorhanden. Eine Möglichkeit, sie zu entfernen (nicht sicher, ob dies der beste Weg ist), ist das Entfernen aller folgenden Seiten durch Aufruf von QWizard.removePage() in Verbindung mit QWizard.nextId().

Beispiel:

from PyQt5.QtWidgets import * 

def end_wizard_after_page_two(): 
    # add finish button to wizard 
    p2.setFinalPage(True) 
    # remove all over buttons 
    while True: 
     id = w.nextId() 
     if id == -1: 
      break 
     w.removePage(id) 

app = QApplication([]) 

# page 1 
p1 = QWizardPage() 
p1.setTitle('Page 1') 

# page 2 
p2 = QWizardPage() 
p2.setTitle('Page 2') 

b = QPushButton('No further pages') 
b.clicked.connect(end_wizard_after_page_two) 
l = QVBoxLayout(p2) 
l.addWidget(b) 

# page 3 
p3 = QWizardPage() 
p3.setTitle('Page 3') 

# wizard 
w = QWizard() 
w.addPage(p1) 
w.addPage(p2) 
w.addPage(p3) 
w.show() 

app.exec_() 

Siehe Methode end_wizard_after_page_two() in diesem Beispiel.

Wenn Sie den Effekt umkehren möchten, müssen Sie alles umgekehrt ausführen (die verbleibenden Seiten erneut hinzufügen und setFinalPage auf False setzen).

+0

Schön. Es klappt. Ich muss mich allerdings fragen, ob es keinen effizienteren Weg gibt, dies zu tun. Für jetzt werde ich es als die Antwort markieren. Vielen Dank. – rbaleksandar

1

Das ist fast ein Jahr zu spät, aber ich denke, ich habe herausgefunden, was das Problem ist. Ihr Anruf an setFinalPage(True), setzt einfach eine Statusflagge in Ihrem QWizardPage. Es wird nicht automatisch an Ihre QWizard weitergegeben.

Es gibt nur ein Signal, das Informationen zurückgibt: completeChanged. Der Name ist etwas irreführend, aber die docs scheinen darauf hinzudeuten, dass es das tut, was Sie wollen, wenn Sie sie gerade richtig gelesen:

Wenn Sie isComplete() reimplementieren, stellen Sie sicher zu emittieren completeChanged(), wenn der Wert von isComplete() Änderungen, um sicherzustellen, Das QWizard aktualisiert den aktivierten oder deaktivierten Status seiner Schaltflächen.

In der Tat, in das gleiche Problem laufen zu haben, konnte ich es beheben, indem

 
if source == 'Calibration file': 
    self.setFinalPage(True) 
    ... 
else: 
    self.setFinalPage(False) 
    ... 
self.completeChanged.emit() 

Die fett gedruckten Linie neu zu tun ist. Es muss in beiden Fällen aufgerufen werden und schaltet die Schaltfläche von "Weiter" auf "Beenden" und zurück, wenn Sie verschiedene Optionen auswählen.