Issue
I have a wizard with three pages. First page is BasicSettings()
, second page is InstallPackages()
and the last page (finish) is Summary()
. BasicSettings()
is for creating a virtual environment. If the 'Install and update Pip' checkbox is left unchecked, the wizard should go directly to the last page Summary()
, else it should go on to InstallPackages()
where the user can install some packages into the created virtual environment. And the last step is from there to go to Summary()
where there is the 'finish' button.
In the code example below the createButton
is connected to the method execute_venv_create()
. When the method has executed the code, a message box pops up, indicating that the process has finished.
Now, when the user clicks Ok I want the wizard to automatically go to the next page defined by QWizard().nextId
. I thought that I could achieve that by invoking QWizard().next()
, but that doesen't work. I tried connecting createButton
to it, but that doesn't have an effect.
How can I make the wizard automatically go on to the next page after execute_venv_create()
finished executing code and the user has confirmed the info message box?
Code to reproduce:
# -*- 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_())
Solution
The change of pages (and the button next/finish, etc.) is handled by the QWizard
and not the page itself.
Since you can't call methods from QWizard
in your QWizardPage
, the easiest way to change the page without clicking on the next button is to use a signal:
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()
Answered By - Dimitry Ernot
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.