Пропустить следующую QWizardPage в зависимости от QCheckBox.isChecked() со страницы до

Я работаю над мастером для установки загруженных пакетов. В определенный момент я хочу пропустить следующий QWizardPageв зависимости от того, установлен ли флажок на странице ранее или нет.

Страница, которую я хочу пропустить, является InstallPackages класс и случай, когда он должен быть пропущен, если флажок self.withPipCBox не проверяется.

Я знаю, что я должен использовать QCheckBox.isChecked() для этого, но как его использовать?


Код:

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QObject, QTimer, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (QApplication, QFileDialog, QGridLayout, QLabel,
                             QVBoxLayout, QWizard, QWizardPage, QProgressBar,
                             QCheckBox, QLineEdit, QGroupBox, QToolButton,
                             QComboBox, QDialog, QHBoxLayout)



class VenvWizard(QWizard):
    """
    Wizard for creating and setting up virtual environments.
    """
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Venv Wizard")
        self.resize(535, 430)
        self.move(578, 183)

        self.setStyleSheet(
            """
            QToolTip {
                background-color: rgb(47, 52, 63);
                border: rgb(47, 52, 63);
                color: rgb(210, 210, 210);
                padding: 2px;
                opacity: 325
            }
            """
        )

        self.addPage(BasicSettings())
        self.addPage(InstallPackages())
        self.addPage(Summary())

class BasicSettings(QWizardPage):
    """
    Basic settings of the virtual environment being created.
    """
    def __init__(self):
        super().__init__()

        folder_icon = QIcon.fromTheme("folder")

        self.setTitle("Basic Settings")
        self.setSubTitle("This wizard will help you to create and set up "
                         "a virtual environment for Python 3. ")

        interpreterLabel = QLabel("&Interpreter:")
        self.interprComboBox = QComboBox()
        interpreterLabel.setBuddy(self.interprComboBox)
        self.interprComboBox.addItem("---")

        venvNameLabel = QLabel("Venv &name:")
        self.venvNameLineEdit = QLineEdit()
        venvNameLabel.setBuddy(self.venvNameLineEdit)

        venvLocationLabel = QLabel("&Location:")
        self.venvLocationLineEdit = QLineEdit()
        venvLocationLabel.setBuddy(self.venvLocationLineEdit)

        selectFolderToolButton = QToolButton()
        selectFolderToolButton.setFixedSize(26, 27)
        selectFolderToolButton.setIcon(folder_icon)
        selectFolderToolButton.setToolTip("Browse")

        placeHolder = QLabel()

        # the 'options' groupbox
        groupBox = QGroupBox("Options")

        self.withPipCBox = QCheckBox("Install and update &Pip")
        self.sitePackagesCBox = QCheckBox(
            "&Make system (global) site-packages dir available to venv")
        self.symlinksCBox = QCheckBox(
            "Attempt to &symlink rather than copy files into venv")
        self.launchVenvCBox = QCheckBox(
            "Launch a terminal with activated &venv after installation")

        # grid layout
        gridLayout = QGridLayout()
        gridLayout.addWidget(interpreterLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.interprComboBox, 0, 1, 1, 2)
        gridLayout.addWidget(venvNameLabel, 1, 0, 1, 1)
        gridLayout.addWidget(self.venvNameLineEdit, 1, 1, 1, 2)
        gridLayout.addWidget(venvLocationLabel, 2, 0, 1, 1)
        gridLayout.addWidget(self.venvLocationLineEdit, 2, 1, 1, 1)
        gridLayout.addWidget(selectFolderToolButton, 2, 2, 1, 1)
        gridLayout.addWidget(placeHolder, 3, 0, 1, 2)
        gridLayout.addWidget(groupBox, 4, 0, 1, 3)
        self.setLayout(gridLayout)

        # 'options' groupbox
        groupBoxLayout = QVBoxLayout()
        groupBoxLayout.addWidget(self.withPipCBox)
        groupBoxLayout.addWidget(self.sitePackagesCBox)
        groupBoxLayout.addWidget(self.symlinksCBox)
        groupBoxLayout.addWidget(self.launchVenvCBox)
        groupBox.setLayout(groupBoxLayout)

class InstallPackages(QWizardPage):
    """
    Install packages via `pip` into the created virtual environment.
    """
    def __init__(self):
        super().__init__()

        self.setTitle("Install Packages")
        self.setSubTitle("Specify the packages which you want Pip to "
                         "install into the virtual environment.")

        # just some content for testing
        TestLabel = QLabel("This is a test label:", self)
        TestLineEdit = QLineEdit(self)
        TestLabel.setBuddy(TestLineEdit)

        TestLabel2 = QLabel("This is a test label:", self)
        TestLineEdit2 = QLineEdit(self)
        TestLabel2.setBuddy(TestLineEdit2)

        v_layout = QVBoxLayout(self)
        v_layout.addWidget(TestLabel)
        v_layout.addWidget(TestLineEdit)
        v_layout.addWidget(TestLabel2)
        v_layout.addWidget(TestLineEdit2)
        self.setLayout(v_layout)


    def initializePage(self):
        pass


class Summary(QWizardPage):
    def __init__(self):
        super().__init__()

        self.setTitle("Summary")
        self.setSubTitle("...............")



if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    wizard = VenvWizard()
    wizard.show()

    sys.exit(app.exec_())

1 ответ

Решение

Вам необходимо реализовать nextId() страницы мастера или самого мастера (который по умолчанию вызывает currentPage().nextId()).

В первом случае вам нужно сохранить или получить ссылку на две страницы, но это также можно сделать, переопределив nextId() экземпляра: это виртуальная функция, что означает, что она может быть переопределена в экземпляре из самого мастера, что позволяет вам немного упростить вещи, так как у вас есть доступ к pageId как только вы добавите их:

        basicSettings = BasicSettings()
        self.addPage(basicSettings)
        installId = self.addPage(InstallPackages())
        summaryId = self.addPage(Summary())
        basicSettings.nextId = lambda: installId if basicSettings.interprComboBox.isChecked() else summaryId

Вы можете сделать почти то же самое в nextId() переопределение мастера, пока вы сохраняете ссылку на страницу, которая содержит хотя бы флажок.
Вот немного другой подход к методу, показанному выше:

class VenvWizard(QWizard):
    def __init__(self):
        super().__init__()
        [...]
        self.basicSettings = BasicSettings()
        self.addPage(self.basicSettings)
        [...]

    def nextId(self):
        if self.currentPage() == self.basicSettings:
            # since python bools can behave as integers, you can add
            # 0 or 1 to the pageId using the isChecked() result
            return self.currentId() + 1 + self.basicSettins.interprComboBox.isChecked()
            # if you need the opposite (skip if unchecked) use this instead
            #return self.currentId() + 1 + (not self.basicSettins.interprComboBox.isChecked())

        return QtWidgets.QWizard.nextId(self)

Кстати, приведенный выше пример будет работать только для непрерывных номеров идентификаторов, что означает, что он не будет работать должным образом, если вы используете "нелинейные" идентификаторы с setPage(id, page) вместо основного addPage(page) (то же самое происходит, если вы хотите пропустить более одной страницы, очевидно); в этом случае вам понадобится ссылка на два идентификатора страницы:

class VenvWizard(QWizard):
    def __init__(self):
        super().__init__()
        [...]
        self.basicSettings = BasicSettings()
        self.addPage(self.basicSettings)
        self.installId = self.addPage(InstallPackages())
        self.summaryId = 20
        self.setPage(self.summaryId, Summary())

    def nextId(self):
        if self.currentPage() == self.basicSettings:
            if self.basicSettins.interprComboBox.isChecked():
                return self.installId
            return self.summaryId
        return QtWidgets.QWizard.nextId(self)

PS: пожалуйста, постарайтесь, чтобы примеры были как можно меньше. На самом деле нет необходимости публиковать все, что содержит ваш код: раздражает только различие между кодом, который имеет смысл или бесполезен для вопроса, и отговаривает людей, желающих помочь, даже пытаться проверить ваш код.

Другие вопросы по тегам