【问题标题】:Skip the next QWizardPage depending on QCheckBox.isChecked() from the page before根据前一页的 QCheckBox.isChecked() 跳过下一个 QWizardPage
【发布时间】:2019-12-08 10:23:49
【问题描述】:

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

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qwizardpage


    【解决方案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)
    

    顺便说一句,上面的示例仅适用于连续的 id 编号,这意味着如果您使用带有setPage(id, page) 而不是基本的addPage(page) 的“非线性”id,它将无法正常运行(如果您愿意,也一样显然要跳过一页以上);如果是这种情况,您将需要对这两个页面 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:请尽量减少示例。确实没有必要发布您的代码包含的所有内容:区分对问题有意义或无用的代码只会让人烦恼,甚至会阻止愿意提供帮助的人甚至尝试检查您的代码。

    【讨论】:

      猜你喜欢
      • 2014-04-01
      • 1970-01-01
      • 2022-01-10
      • 2019-10-04
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 2011-07-15
      相关资源
      最近更新 更多