簡體   English   中英

QTreeWidgetItem上的PyQt有效性檢查

[英]PyQt validity check on QTreeWidgetItem

我正在構建一個QTreeWidget,在其中實現添加新項和重命名功能。 我想檢查用戶提供的新名稱的有效性,包括:

  1. 名稱只能包含有效字符列表。 這已經通過將QRegExpValidator添加到子類QItemDelegate並將新的委托分配給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-為項目委托使用多個驗證器相關,但是沒有給出答案,只是在注釋中提出了一個建議,即應該將QValidator子類QValidator以在同一正則表達式中處理名稱沖突檢測。 不知道如何執行此操作,在這些QTreeWidgetItems之前創建並分配了驗證器,不是嗎?

這個問題也使QTreeWidgetItem在同級中唯一 沒有人回答。

我找到了一個解決方案:

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_())

它仍在使用自定義委托來檢查無效字符。 我嘗試通過將QValidator子類QValidator並為其提供當前的同級列表,在委托的編輯器中添加同級沖突檢查。 但是,這將執行即時驗證,而不是提交后驗證。 例如,當檢查“ abc”與“ abc”沖突時,即使我打算鍵入“ abcd”,我也無法在“ ab”之后鍵入“ c”。

我發現了有關edit: editting failed 問題 edit: editting failed錯誤,似乎Qt.QueuedConnection可以解決問題。 因此, tree.itemChanged連接到重復檢查功能,如果檢查失敗,它將提示用戶再次輸入名稱。 可以選擇彈出提示沖突的工具提示。

雖然可能不是理想的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM