首页 > 解决方案 > 根据前一页的 QCheckBox.isChecked() 跳过下一个 QWizardPage

问题描述

我正在开发一个安装下载包的向导。在特定的点上,我想跳过下一个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_())

标签: pythonpython-3.xpyqtpyqt5qwizardpage

解决方案


您需要实现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)

顺便说一句,上面的示例仅适用于连续的 ID 号,这意味着如果您使用“非线性”IDsetPage(id, page)而不是基本ID,它将无法正常运行addPage(page)(如果您想跳过多个页面,显然也是如此) ; 如果是这种情况,您将需要对两个页面 ID 的引用:

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:请尽量减少示例。确实没有必要发布您的代码包含的所有内容:区分对问题有意义或无用的代码只会让人烦恼,甚至会阻止愿意提供帮助的人甚至尝试检查您的代码。


推荐阅读