PyQt 获取 QWizard 中所有注册字段的集合

PyQt obtaining collection of all registered fields in QWizard

我正在开发一个简单的 QWizard,它会在其页面上显示一些单选按钮。给定页面上的按钮都是同一 QButtonGroup 的一部分。根据按钮组中的选择,页面本身注册为自定义字段:

class Page1(QWizardPage):
     selectionChanged = pyqtSignal('QString')

     def __init__(self, name):
         self.group = QButtonGroup()
         self.group.addButton(QRadioButton("a"))
         self.group.addButton(QRadioButton("b"))
         self.group.addButton(QRadioButton("c"))
         self.registerField(name, self, 'selection', self.selectionChanged)

    @pyqtProperty('QString')
    def selection(self):
        checkedButton = self.group.checkedButton()
        return checkedButton.text() if checkedButton else None

    def nextId(self): return -1

我最终将 self 注册为包含字段 属性 的小部件,仅仅是因为 QButtonGroup 不是 QWidget。所有其他页面看起来都非常像这个(我实际上使用 base class 来完成所有常见的工作,这只是一个最小的例子)。

我希望能够获得 QWizard 中所有已注册字段的列表。我没有找到 Qt 提供的任何允许我这样做的方法,所以我通过覆盖每个页面的 registerField 方法以及向导的 addPage:

方法的行为来解决这个问题
def registerField(self, name, *args, **kwargs):
    self.field_names.add(name)
    if self.wizard() is not None:
        self.wizard().field_names.add(name)
    super().registerField(name, *args, **kwargs)

def addPage(self, page, *args, **kwargs):
    self.field_names.union(page.field_names)
    return super().addPage(page, *args, **kwargs)

然后我可以使用父QWizardfield_set属性结合QWizard.field to access all the values. This seems a bit redundant and therefore unnecessary. Is there a method in Qt to access the complete collection of fields? The relevant section in the documentation没有提到任何东西,但还有很多其他细节它省略了,所以这不是很有说服力。

我的假设是 PyQt4 和 PyQt5 的功能(如果存在的话)是相同的。如果不是,我更喜欢 PyQt5 的答案,因为那是我目前正在使用的。

你说如果答案是否定的,那肯定是"pretty convincing."你承认文档中没有提到你想要的功能,我要指出的是列表中没有这样的功能QWizard 的 public 个函数。因此,所需的函数(如果存在的话)是 未记录的 。对我来说,仅此考虑就是 "pretty convincing" 不使用它的理由。 Qt 的下一个版本可能没有那个功能,或者它可能不会以同样的方式工作。

同时,您有一个可接受的解决方案,其中包含八行直截了当的 python 代码。鉴于在调用未记录的函数(如果你能找到它)之间做出选择,python 解决方案在所有实际方面都非常优越。

但是,您的 Python 代码可能存在问题。您覆盖了函数 QWizard.addPage,但还有另一个函数 QWizard.removePage 也应该被覆盖。我更喜欢的另一种方法是根本不将 field_names 存储在 QWizard 中,而仅存储在各个页面中。给QWizard添加一个方法,动态构建一组当前所有的field_names:

def all_field_names(self):
    return {s for page_id in self.pageIds() for s in self.page(page_id).field_names}

[我没有很好的方法来测试这个函数,但我想你明白了。]现在你删除覆盖的方法 QWizard.addPage,从 QWizard,去掉中间两行register_field。现在您只有五行 Python 代码,无论页面如何添加或删除,它们都可以正常工作。而且您不再将字段名称存储在两个地方。

就其价值而言,每当我面临在使用 Qt 功能还是基本 Python 功能之间做出选择时,我总是倾向于 Python。我使用线程而不是 QThreads,线程锁和定时器而不是 Qt 等价物,Python 方法对象和回调而不是自定义插槽和信号。 Qt 是为 C++ 程序员编写的,这通常意味着它并不像我想要的那样 "pythonic"。