根据内容的变化从 QWizardPage 动态添加/删除 Finish

Posted

技术标签:

【中文标题】根据内容的变化从 QWizardPage 动态添加/删除 Finish【英文标题】:Dynamically add/remove Finish from QWizardPage based on change in its content 【发布时间】:2016-06-12 22:08:43 【问题描述】:

我正在关注license wizard(使用PyQt5)上的教程,试图学习如何创建非线性向导。但是我似乎陷入了一个问题。

我想要一个带有QComboBox 的页面,其中所选项目确定当前包含组合框的QWizardPage 是否是最后一页。

目前页面包含的内容如下:

class CalibrationPageSource(QWizardPage):
    def __init__(self, parent):
        super(CalibrationPageSource, self).__init__(parent)
        self.setTitle('Calibration Wizard')
        self.setSubTitle('Select the source for the calibration')

        layout = QVBoxLayout()
        label = QLabel('''
            <ul>
                <li><b>From calibration file</b>: browse and select an existing YAML calibration file that contains the camera matrix and distortion coefficients (for example from a previous calibration)</li>
                <li><b>From image files</b>: browse and select one or more image files with the calibration pattern visible inside each</li>
                <li><b>From stream</b> - if the calibration node is connected to an active <b><i>Device node</i></b> you can use its image stream to interactively calibrate your device</li>
            </ul>
        ''')
        label.setWordWrap(True)
        layout.addWidget(label)

        layout_sources = QHBoxLayout()
        label_sources = QLabel('Source:')
        self.selection_sources = QComboBox()
        self.selection_sources.addItem('Calibration file')
        self.selection_sources.addItem('Image files')
        self.selection_sources.addItem('Stream')
        self.selection_sources.currentIndexChanged['QString'].connect(self.source_changed)
        self.selection_sources.setCurrentIndex(1)
        layout_sources.addWidget(label_sources)
        layout_sources.addWidget(self.selection_sources)
        layout.addLayout(layout_sources)

        self.setLayout(layout)

    @pyqtSlot(str)
    def source_changed(self, source):
        if source == 'Calibration file':
            self.setFinalPage(True)
            # TODO Add file dialog
        else:
            self.setFinalPage(False)
            # TODO Remove file dialog (if present)

每当self.selection_sources 的当前项目更改为Calibration file 时,我想跳过向导的其余部分,即使页面最终化。在这种情况下,我想删除 Next 按钮。在所有其他情况下(目前只有两个:Image filesStream)我想让向导正常运行,而不是作为最后一页。

I have tried implementing a custom isComplete(...) but the problem is that it disables both Next and Finish when Calibration file is selected.我可以忍受禁用Next 按钮(而不是完全隐藏它),但禁用Finish 在我的情况下基本上没有意义。我真的很惊讶Next 按钮的存在。当到达最后一页时,它不应该完全消失吗?

任何想法如何解决这个问题?我考虑过遍历QWizardPage 中的项目并手动禁用/隐藏Next 按钮,但我希​​望有一种更简单、开箱即用的方法来做到这一点。在当前状态下,Finish 的动态插入正在运行,但是由于 Next 按钮,向导的转换没有正确设置。

【问题讨论】:

【参考方案1】:

这已经晚了将近一年,但我想我弄清楚了问题所在。您对setFinalPage(True) 的调用,只需在您的QWizardPage 中设置一个状态标志。它不会自动传播回您的QWizard

只有一个信号可以将信息传播回来:completeChanged。这个名字有点误导,但文档似乎表明,如果你读得恰到好处,它会做你想做的事:

如果您重新实现isComplete(),请确保在isComplete() 的值发生变化时发出completeChanged(),以确保QWizard 更新其按钮的启用或禁用状态。

事实上,遇到同样的问题,我可以通过这样做来解决它

如果源 == '校准文件': self.setFinalPage(True) ... 别的: self.setFinalPage(假) ... self.completeChanged.emit()

粗体线是新的。在这两种情况下都需要调用它,并且会在您选择不同的选项时将按钮从“下一步”切换到“完成”并返回。

【讨论】:

我最终不得不发出 completeChanged() 以动态更改 QWizardPage::nextId() 值。【参考方案2】:

在您的代码中,您已经使用QWizardPage.setFinalPage(True) 将完成按钮添加到中间页面。现在下一个按钮仍然存在。删除它的一种方法(不确定这是否是最好的方法)是通过调用 QWizard.removePage()QWizard.nextId() 来删除所有后续页面。

例子:

from PyQt5.QtWidgets import *

def end_wizard_after_page_two():
    # add finish button to wizard
    p2.setFinalPage(True)
    # remove all over buttons
    while True:
        id = w.nextId()
        if id == -1:
            break
        w.removePage(id)

app = QApplication([])

# page 1
p1 = QWizardPage()
p1.setTitle('Page 1')

# page 2
p2 = QWizardPage()
p2.setTitle('Page 2')

b = QPushButton('No further pages')
b.clicked.connect(end_wizard_after_page_two)
l = QVBoxLayout(p2)
l.addWidget(b)

# page 3
p3 = QWizardPage()
p3.setTitle('Page 3')

# wizard
w = QWizard()
w.addPage(p1)
w.addPage(p2)
w.addPage(p3)
w.show()

app.exec_()

参见本例中的方法end_wizard_after_page_two()

如果您想反转效果,您必须反向执行所有操作(再次添加剩余页面并将 setFinalPage 设置为 False)。

【讨论】:

不错。有用。我不得不怀疑是否没有更有效的方法来做到这一点。现在我将其标记为答案。谢谢。

以上是关于根据内容的变化从 QWizardPage 动态添加/删除 Finish的主要内容,如果未能解决你的问题,请参考以下文章

如何根据内容动态制作 Swift UIStackView 大小?

如何获得根据标签内容动态变化的 UIView 的高度 - Swift

根据内容动态调整 iframe 高度

从 InnerHTML 中的代码隐藏向页面添加 ASP 控件

谁知道怎么用ajax实现选择下拉框的时候动态从数据库读取数据吗

如何根据内容动态收缩 WebView 大小?