单击 QPushButton 后执行一些代码,完成后自动转到下一个 QWizardPage

After QPushButton clicked execute some code and when finished automatically go to next QWizardPage

我有一个包含三个页面的向导。第一页是 BasicSettings(),第二页是 InstallPackages(),最后一页(完成)是 Summary()BasicSettings() 用于创建虚拟环境。如果未选中 'Install and update Pip' 复选框,向导应该直接转到最后一页 Summary(),否则它应该继续到 InstallPackages()用户可以将一些包安装到创建的虚拟环境中。最后一步是从那里转到 Summary() 那里有 'finish' 按钮。

在下面的代码示例中,createButton 连接到方法 execute_venv_create()。当该方法执行完代码时,会弹出一个消息框,指示该过程已完成。

现在,当用户单击 确定时 我希望向导自动转到 QWizard().nextId 定义的下一页。我以为我可以通过调用 QWizard().next() 来实现,但这不起作用。我尝试将 createButton 连接到它,但这没有效果。

如何让向导在execute_venv_create()执行完代码并且用户确认信息消息框后自动进入下一页?


重现代码:

# -*- coding: utf-8 -*-
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QGridLayout, QLabel, QCheckBox,
                             QHBoxLayout, QVBoxLayout, QToolButton, QWizard,
                             QWizardPage, QComboBox, QTableView, QLineEdit,
                             QGroupBox, QPushButton, QMessageBox)


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

        self.setWindowTitle("Venv Wizard")
        self.resize(635, 480)
        self.move(528, 153)

        basicSettings = BasicSettings()
        self.addPage(basicSettings)

        installId = self.addPage(InstallPackages())
        summaryId = self.addPage(Summary())

        # go to last page if pip wasn't selected else go to the install page
        basicSettings.nextId = (
            lambda: installId if basicSettings.withPipCBox.isChecked()
            else summaryId
        )

        # ...

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

        folder_icon = QIcon.fromTheme("folder")

        self.setTitle("Basic Settings")
        self.setSubTitle("..........................."
                         "...........................")

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

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

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

        self.selectDirToolButton = QToolButton(icon=folder_icon)
        self.selectDirToolButton.setFixedSize(26, 27)

        placeHolder = QLabel()

        # 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"
        )
        self.createButton = QPushButton(
            "&Create", self,
            clicked=self.execute_venv_create,
        )
        self.createButton.setFixedWidth(90)

        # box layout containing the create button
        h_BoxLayout = QHBoxLayout()
        h_BoxLayout.setContentsMargins(495, 5, 0, 0)
        h_BoxLayout.addWidget(self.createButton)

        # 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(self.selectDirToolButton, 2, 2, 1, 1)
        gridLayout.addWidget(placeHolder, 3, 0, 1, 2)
        gridLayout.addWidget(groupBox, 4, 0, 1, 3)
        gridLayout.addLayout(h_BoxLayout, 5, 0, 1, 0)
        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)

    def execute_venv_create(self):
        """
        Execute the creation process.
        """
        # do something, then display info message
        QMessageBox.information(self, "Done", "message text")
        # when user clicks 'Ok', go to the next page defined in .nextId


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

        self.setTitle("Install Packages")
        self.setSubTitle("..........................."
                         "...........................")

        verticalLayout = QVBoxLayout()
        gridLayout = QGridLayout(self)

        pkgNameLabel = QLabel("Package name:")
        self.pkgNameLineEdit = QLineEdit()
        self.searchButton = QPushButton("Search")
        resultsTable = QTableView(self)

        gridLayout.addWidget(pkgNameLabel, 0, 0, 1, 1)
        gridLayout.addWidget(self.pkgNameLineEdit, 0, 1, 1, 1)
        gridLayout.addWidget(self.searchButton, 0, 2, 1, 1)
        gridLayout.addWidget(resultsTable, 1, 0, 1, 3)

        verticalLayout.addLayout(gridLayout)

        # ...

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

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

        # ...

    def initializePage(self):
        pass


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    wiz = VenvWizard()
    wiz.exec_()

    sys.exit(app.exec_())

页面(和按钮 next/finish 等)的更改由 QWizard 而不是页面本身处理。

由于您无法在 QWizardPage 中调用 QWizard 的方法,因此无需单击 下一步 按钮即可更改页面的最简单方法是使用信号:

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

        self.setWindowTitle("Venv Wizard")
        self.resize(635, 480)
        self.move(528, 153)

        self.basicSettings = BasicSettings()
        self.basicSettingsId = self.addPage(self.basicSettings)

        self.installId = self.addPage(InstallPackages())
        self.summaryId = self.addPage(Summary())


        self.basicSettings.done.connect(self.next)

        # go to last page if pip wasn't selected else go to the install page

    def nextId(self):
        # Process the flow only if the current page is basic settings
        if self.currentId() != self.basicSettingsId:
            return super().nextId()

        if self.basicSettings.withPipCBox.isChecked():
            return self.installId
        else:
            return self.summaryId
    done = pyqtSignal()
    def execute_venv_create(self):
        """
        Execute the creation process.
        """
        # do something, then display info message
        ok = QMessageBox.information(self, "Done", "message text")
        # when user clicks 'Ok', go to the next page defined in .nextId
        self.done.emit()