使用 QStyledItemDelegate 验证 QTreeWidget 的特定列无法正常工作

Posted

技术标签:

【中文标题】使用 QStyledItemDelegate 验证 QTreeWidget 的特定列无法正常工作【英文标题】:validating specific column of QTreeWidget using QStyledItemDelegate not working properly 【发布时间】:2021-05-16 17:06:55 【问题描述】:

我有一个 3 列的 QTreeWidget,只有第 3 列应该有一个双重验证器。我的问题是它有点工作。 QLineEdit 不会在 100 处停止,它会继续前进。

我错过了什么;让它在不让用户输入高于 100 的任何内容的情况下仍然编辑 lineEdit?

import sys

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class Delegate(QStyledItemDelegate):
    'Changes number of decimal places in gas analysis self.chosen table'

    def __init__(self, decimals, parent=None):
        super().__init__(parent)
        self.nDecimals = decimals

    def createEditor(self, parent, option, index):
        editor = QLineEdit(parent)
        editor.setValidator(QDoubleValidator(0,100, 15))
        return editor

    def setEditorData(self, editor, index):
        if index.column() == 2 and index.data() is not None:
            editor.setText(str(float(index.data())))


class Widget(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent=None)

        self.tree_widget = QTreeWidget()
        self.tree_widget.setItemDelegate(Delegate(self.tree_widget))
        self.tree_widget.setHeaderLabels(["Value1", "Value2", "Value3"])

        self.setCentralWidget(self.tree_widget)

        for vals in [("h", "20.0", "40.0"), ("k", "25.0", "50.0")]:
            it = QTreeWidgetItem(vals)
            it.setFlags(it.flags()| Qt.ItemIsEditable)
            self.tree_widget.addTopLevelItem(it)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec_())

【问题讨论】:

首先,实现是不够的,因为它没有正确覆盖其他列,并且您正在创建的实例的参数与__init__ 的签名不匹配。但是,最重要的是,为什么要使用 QLineEdit 而不是 QDoubleSpinBox? 【参考方案1】:

QDoubleValidator 仅尝试验证用户输入的文本,如果不符合要求,则不会保存信息,这就是您的情况所观察到的。如果您想定义您希望用户在特定情况下使用哪些值,最好使用 QDoubleSpinBox 作为编辑器:

class Delegate(QStyledItemDelegate):
    def __init__(self, decimals, parent=None):
        super().__init__(parent)
        self.nDecimals = decimals

    def createEditor(self, parent, option, index):
        editor = QDoubleSpinBox(
            parent, minimum=0, maximum=100.0, decimals=self.nDecimals
        )
        return editor

    def setEditorData(self, editor, index):
        if index.data() is not None:
            try:
                value = float(index.data())
            except Exception as e:
                print("error", e)
            else:
                editor.setValue(value)


class Widget(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent=None)

        self.tree_widget = QTreeWidget()
        self.tree_widget.setHeaderLabels(["Value1", "Value2", "Value3"])
        self.tree_widget.setItemDelegateForColumn(2, Delegate(15, self.tree_widget))

        self.setCentralWidget(self.tree_widget)

        for vals in [("h", "20.0", "40.0"), ("k", "25.0", "50.0")]:
            it = QTreeWidgetItem(vals)
            it.setFlags(it.flags() | Qt.ItemIsEditable)
            self.tree_widget.addTopLevelItem(it)

注意:我已经修改了列选择,因为在 OP 的初始实现中,所有列都使用相同的编辑器,这显然与其相同的要求相矛盾,所以不要使用 setItemDelegate()我用过 setItemDelegateForColumn()。

【讨论】:

以上是关于使用 QStyledItemDelegate 验证 QTreeWidget 的特定列无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 QStyledItemDelegate 在 QTreeWidget 中拥有不同高度的 QTreeWidgetItems?

Qt表格中的自定义编辑组件---------------自定义代理QStyledItemDelegate

QListView 与 CustomWIdget 使用 QStyledItemDelegate

在带有 QSqlQueryModel 的 QListView 上使用 QStyledItemDelegate

QStyledItemDelegate 部分选择默认 QLineEdit 编辑器的文本

PyQt:在 QStyledItemDelegate 中使用 QTextEdit 作为编辑器