【问题标题】:Getting a QTreeView on a QWizardPage to update properly在 QWizardPage 上获取 QTreeView 以正确更新
【发布时间】:2019-08-19 06:01:25
【问题描述】:

我在QWizardPage(比如qwpage2)上有一个QTreeView 小部件,其中一列信息的标志取决于另一个QRadioButton 上的状态QWizardPage(比如@ 987654326@)。

treeview列的原始属性是在qwpage2initializePage方法中设置的。如果我通过页面Next >,一切正常。但是,如果我将< Backqwpage2 更改为qwpage1 上的单选按钮,并将Next > 更改为qwpage2,则标志不会更新。

我在qwpage1 上有类似以下内容(在 PyQt5 中):

rbtn1 = QRadioButton()
rbtn2 = QRadioButton()

self.registerField ("remove_checkbox", rbtn1)
self.registerField ("add_checkbox", rbtn2)

self.checked_choice.addButton(rbtn1)
self.checked_choice.addButton(rbtn2)

qwpage2


add_checkbox = self.field("add_checkbox")

p = QStandardItem()
if add_checkbox:
  p.setFlags(p.flags() | Qt.ItemIsUserCheckable)
else:
  p.setFlags(Qt.NoItemFlags)

如果页面之前已初始化,我如何更改与我的树视图列关联的标志状态(基本上是复选框的存在)?

感谢您的帮助

【问题讨论】:

    标签: python pyqt


    【解决方案1】:

    问题不在于您从下一个返回后返回该页面时,因为始终调用initializePage(),无论“上一个”页面是页面索引中的上一个还是下一个(这是有道理的,因为页面顺序并不总是必须遵循“普通索引顺序”,因为它是从QWizard.nextId() 返回的,默认情况下调用当前页面的QWizardPage.nextId(),甚至可以返回一个小于当前)。
    也就是说,在一种情况下,initializePage() 只被调用一次,如果你设置了QWizard.IndependentPages 选项,就会发生这种情况。如果你真的需要使用它,我认为唯一的选择是通过覆盖页面的 showEvent(event)only if not event.spontaneous() 来设置值(否则即使页面是最小化后再次显示)。

    这里真正重要的是项目委托的复选框通常显示如果为其索引设置了Qt.CheckStateRole,因为设置Qt.ItemIsUserCheckable仅意味着用户可以设置项目状态复选框可见。
    事实上,除非某些特定的 OS/QtStyle 起作用,否则设置该标志根本不会产生任何影响,即使发生这种情况,一旦检查状态设置为三种状态中的任何一种(未检查、部分检查或选中)不会有任何区别:无论如何都会显示。

    虽然这看起来有点违反直觉,但从 source code 可以清楚地看出它的行为,其中 StyleOptionViewItem 功能 HasCheckIndicator 设置为 True 当且只有 data(role=CheckStateRole) 不是“Null”时,如 Python 的 None .

    无关紧要的注意事项:请注意,如果您使用更高级的模型(例如 QSql 模型),则“未设置”值(如在“Null”QVariant 中,例如,该字段没有数据集) 总是 Python 的 None,而是“QPyNullVariant”。


    考虑到上述概念,您应该在 QWizardPage 的__init__ 中设置模型及其项,然后仅使用initializePage 设置其标志。

    class Page2(QtWidgets.QWizardPage):
        def __init__(self, parent=None):
            QtWidgets.QWizardPage.__init__(self, parent)
            layout = QtWidgets.QGridLayout()
            self.setLayout(layout)
            self.tree = QtWidgets.QTreeView()
            layout.addWidget(self.tree)
    
            self.model = QtGui.QStandardItemModel()
            self.tree.setModel(self.model)
            self.model.dataChanged.connect(self.setCurrentState)
    
            self.addCheckItem = QtGui.QStandardItem('item')
            self.model.appendRow(self.addCheckItem)
            # remember the default flags
            self.defaultFlags = self.addCheckItem.flags()
            # set the current "add_checkbox" value to None, which means that it
            # has *no* state set at all, not even an Unchecked one
            self.currentState = None
    
        def setCurrentState(self, topLeft, bottomRight):
            # remember the new check state
            self.currentState = self.addCheckItem.checkState()
    
        def initializePage(self):
            if self.field('add_checkbox'):
                # apply the new flags to allow the user to set the check state
                self.addCheckItem.setFlags(
                    self.defaultFlags | QtCore.Qt.ItemIsUserCheckable)
                # set the state if it has been previously set
                if self.currentState is None:
                    self.addCheckItem.setCheckState(QtCore.Qt.Unchecked)
                else:
                    self.addCheckItem.setCheckState(self.currentState)
            else:
                # prevent notifying setCurrentState() slot that we're changing the 
                # value, while still remembering the check state;
                # note that blogking model signals is not a good practice, as it
                # prevents the view to receive model changes, which usually results
                # in painting, size, scrolling and mouse interaction issues, but we
                # can ignore that in this case, since those changes are only taken
                # into account once the view is shown, assuming that the view will
                # update once it will be shown, and that will only happen *after*
                # initializePage returns
                self.model.blockSignals(True)
                self.addCheckItem.setData(None, QtCore.Qt.CheckStateRole)
                self.model.blockSignals(False)
    

    【讨论】:

    • 感谢您花时间写出如此完整且内容丰富的答案!我只使用了大约三周的 PyQt,非常感谢像您这样的 Qt 工具包大师的见解。随着对其中一些问题的更好理解,我将尝试按照您的建议分解我的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-18
    相关资源
    最近更新 更多