gpt4 book ai didi

python - PyQt 对 QTreeWidgetItem 的有效性检查

转载 作者:太空宇宙 更新时间:2023-11-03 21:19:07 24 4
gpt4 key购买 nike

我正在构建一个 QTreeWidget,在其中实现添加新项目和重命名功能。我想检查用户给出的新名称的有效性,包括:

  1. 名称只能包含有效字符列表。这已经通过将 QRegExpValidator 添加到子类 QItemDelegate 并将新委托(delegate)分配给 QTreeWidget 来实现。
  2. 该名称不能与其同级名称冲突。我现在不知道要实现这一点。

这是我当前的尝试:

import sys
from PyQt5.QtWidgets import QItemDelegate, QTreeWidget, QVBoxLayout, QLineEdit,\
QMainWindow, QWidget, QTreeWidgetItem, QApplication
from PyQt5.QtCore import QRegExp, Qt
from PyQt5.QtGui import QRegExpValidator


class TreeWidgetDelegate(QItemDelegate):
def __init__(self, parent=None):
QItemDelegate.__init__(self, parent=parent)

def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
reg=QRegExp('[A-z0-9\[\]_-]+')
vd=QRegExpValidator(reg)

editor.setValidator(vd)
return editor


class MainWindow(QMainWindow):
def __init__(self):
super(self.__class__, self).__init__()
frame=QWidget()
self.setCentralWidget(frame)
hl=QVBoxLayout()
frame.setLayout(hl)

self.tree=QTreeWidget(self)
mydele=TreeWidgetDelegate()
self.tree.setItemDelegate(mydele)
hl.addWidget(self.tree)

# add treewidgetitems
for ii in range(5):
item=QTreeWidgetItem([str(ii),])
self.tree.addTopLevelItem(item)

self.tree.itemDoubleClicked.connect(self.rename)
self.tree.itemChanged.connect(self.checkString)

dele=self.tree.itemDelegate()
print('dele',dele)

self.show()

def rename(self):
item=self.tree.selectedItems()
if item:
item=item[0]
item.setFlags(item.flags() | Qt.ItemIsEditable)
self.tree.scrollToItem(item)
self.tree.editItem(item)

def checkString(self,item,column):
text=item.data(0,column)
print('newname:',text)

siblings=[self.tree.topLevelItem(ii).data(0,0) for ii in \
range(self.tree.topLevelItemCount())]
print('siblings:',siblings)

if text in siblings:
print('invalid name')

# this gives "edit: editing failed"
self.tree.editItem(item)


if __name__ == "__main__":
app = QApplication(sys.argv)
form = MainWindow()
form.show()
sys.exit(app.exec_())

特别是,我正在连接tree.itemChanged.connect(self.checkString),并且checkString()检查名称冲突。但是,当检测到冲突时,我不知道如何恢复为旧名称并重新进入编辑模式并让用户再次重命名。 tree.editItem(item) 会抛出错误

edit: editing failed

。我猜这会再次触发信号并最终陷入无限循环?

我找到了PyQt - Using Multiple Validators for Item Delegates相关,但没有给出答案,只是在评论中建议应该子类 QValidator 来处理同一正则表达式中的名称冲突检测。不知道如何做到这一点,验证器是在那些 QTreeWidgetItems 之前创建和分配的,不是吗?

还有这个问题Make QTreeWidgetItem unique among siblings 。没有人回答。

最佳答案

我找到了解决方案:

import sys
from PyQt5.QtWidgets import QItemDelegate, QTreeWidget, QVBoxLayout, QLineEdit,\
QMainWindow, QWidget, QTreeWidgetItem, QApplication
from PyQt5.QtCore import QRegExp, Qt
from PyQt5.QtGui import QRegExpValidator


class TreeWidgetDelegate(QItemDelegate):
def __init__(self, parent=None):
QItemDelegate.__init__(self, parent=parent)

def createEditor(self, parent, option, index):
editor = QLineEdit(parent)
# allow only these chars
reg=QRegExp('[A-z0-9\[\]_-]+')
regvd=QRegExpValidator(reg)
editor.setValidator(regvd)
return editor


class MainWindow(QMainWindow):

def __init__(self):
super(QMainWindow, self).__init__()
frame=QWidget()
self.setCentralWidget(frame)
hl=QVBoxLayout()
frame.setLayout(hl)

self.tree=QTreeWidget(self)
hl.addWidget(self.tree)

# assign custom delegate to treewidget
dele=TreeWidgetDelegate()
self.tree.setItemDelegate(dele)

# add treewidgetitems
for ii in range(5):
item=QTreeWidgetItem([str(ii)*3,])
self.tree.addTopLevelItem(item)

self.tree.itemDoubleClicked.connect(self.rename)

# QueuedConnection cures the editting failed issue
self.tree.itemChanged.connect(self.checkName, Qt.QueuedConnection)

self.show()

def getSiblings(self,item):
siblings=[self.tree.topLevelItem(ii).data(0,0) for ii in \
range(self.tree.topLevelItemCount())]
item_text=item.data(0,0)
if item_text in siblings:
siblings.remove(item_text)
return siblings

def rename(self):
item=self.tree.selectedItems()
if item:
item=item[0]
item.setFlags(item.flags() | Qt.ItemIsEditable)
self.tree.scrollToItem(item)
self.tree.editItem(item)

def checkName(self,item,column):
text=item.data(0,0)
siblings=self.getSiblings(item)
print('checkName: slibings:', siblings)

if text in siblings:
print('checkName: ivalid')
item.setData(0,0,'New_name_needed')
self.tree.editItem(item)


if __name__ == "__main__":
app = QApplication(sys.argv)
form = MainWindow()
form.show()
sys.exit(app.exec_())

它仍然使用自定义委托(delegate)来检查无效字符。我尝试通过子类化 QValidator 并为其提供当前同级列表,在委托(delegate)编辑器中添加同级冲突检查。然而,这将执行即时验证而不是提交后验证。例如,当检查“abc”与“abc”时'abc' 冲突,即使我想输入 'abcd',我也无法在 'ab' 之后输入 'c'。

我找到了this question关于 edit: editting failed 错误,似乎 Qt.QueuedConnection 可以解决问题。所以tree.itemChanged连接到了重复检查功能,如果检查失败,它会提示用户重新输入名称。人们可以选择弹出一个工具提示来通知冲突。

但这可能不是理想的解决方案。

关于python - PyQt 对 QTreeWidgetItem 的有效性检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54443129/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com