QValidator只接受列表中的字符串

时间:2017-12-10 20:18:00

标签: python

如何在pyside中创建QValidator只限制QLineEdit只接受来自预定义字符串列表的文本输入?我设法让自动填充功能无法显示我想要的区分大小写。

enter image description here

import os
import sys
from PySide import QtCore, QtGui


available_tags = ['Animals','Brick','Buildings','Concrete','Decals','Doors','Fabric','Floors','FX','Ground','Grunge','Landscapes','Manmade','Marble','Metal','Nature','Ornaments','Paper','Plaster','Plastic','Roads','Rock','Roofing','Rust','Signs','Soil','Tiles','Various','Windows','Wood',]


class ExampleWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(ExampleWindow, self).__init__(parent)
        self.resize(300, 200)

        self.available_tags_model = QtGui.QStringListModel(available_tags)
        self.ui_tag_completer = QtGui.QCompleter()
        self.ui_tag_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.ui_tag_completer.setModel(self.available_tags_model)

        self.ui_input = QtGui.QLineEdit()
        self.ui_input.setCompleter(self.ui_tag_completer)
        self.ui_input.setPlaceholderText('enter description...')
        self.ui_input.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp("[A-Za-z0-9_]{0,255}")))

        self.tags_model = QtGui.QStringListModel()
        self.ui_tags_list = QtGui.QListView()
        self.ui_tags_list.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.ui_tags_list.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.ui_tags_list.setModel(self.tags_model)
        self.ui_tags_list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.ui_tags_list.customContextMenuRequested.connect(self.open_tags_list_menu)

        # layout
        self.ui_tags_list.setViewMode(QtGui.QListView.IconMode)
        self.ui_tags_list.setResizeMode(QtGui.QListView.Adjust)
        self.ui_tags_list.setMovement(QtGui.QListView.Static)
        self.ui_tags_list.setSpacing(5)
        self.ui_tags_list.setStyleSheet('''
            QListView::item {
                border: 1px solid rgba(0,0,0,60);
                background: rgba(0,0,0,30);
                border-radius: 2px;
            }
            QListView::item:selected {
                border: 1px solid rgba(70,150,255,255);
                background: rgba(70,150,255,200);
                border-radius: 2px;
            }
        ''')

        # main layout
        main_layout = QtGui.QVBoxLayout()
        main_layout.setContentsMargins(5,5,5,5)
        main_layout.setSpacing(5)
        main_layout.addWidget(self.ui_input)
        main_layout.addWidget(self.ui_tags_list)

        main_widget = QtGui.QWidget()
        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

        # connections
        self.ui_input.returnPressed.connect(self.input_entered)
        self.ui_tags_list.doubleClicked.connect(self.double_clicked_item)
        self.ui_tag_completer.activated.connect(self.tag_entered)

        # menus
        self.create_actions()

    def create_actions(self):
        self.act_delete_tags = QtGui.QAction('Delete', self)
        self.act_delete_tags.triggered.connect(self.remove_items)

        self.menu_tags_list = QtGui.QMenu()
        self.menu_tags_list.addAction(self.act_delete_tags)


    def append_tag(self, val):
        if not val:
            return False

        if val.lower() in [x.lower() for x in self.tags_model.stringList()]:
            return False

        self.tags_model.insertRow(self.tags_model.rowCount())
        index = self.tags_model.index(self.tags_model.rowCount()-1)
        self.tags_model.setData(index, val)


    def remove_items(self):
        self.ui_tags_list.setUpdatesEnabled(False)

        indexes = self.ui_tags_list.selectionModel().selectedIndexes()
        while (len(indexes)):
            self.tags_model.removeRow(indexes[0].row())
            indexes = self.ui_tags_list.selectionModel().selectedIndexes()

        self.ui_tags_list.setUpdatesEnabled(True)


    def input_entered(self):
        text = self.ui_input.text()
        self.append_tag(text)
        self.ui_input.clear()

    def tag_entered(self, text):
        ''


    def double_clicked_item(self, item):
        self.remove_items()


    def open_tags_list_menu(self, position):
        self.menu_tags_list.exec_(self.ui_tags_list.viewport().mapToGlobal(position))


def main():
    app = QtGui.QApplication(sys.argv)
    ex = ExampleWindow()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:2)

我们为标签创建验证器,验证器的优点是它会限制你写文本,在@AakashVerma解决方案的情况下它是部分的,因为它允许你写文本是不在标签中,只在按下输入时检查它。:

class TagsValidator(QtGui.QValidator):
    def __init__(self, tags, *args, **kwargs):
        QtGui.QValidator.__init__(self, *args, **kwargs)
        self._tags = [tag.lower() for tag in tags]

    def validate(self, inputText, pos):
        if inputText.lower() in self._tags:
            return QtGui.QValidator.Acceptable
        len_ = len(inputText)
        for tag in self._tags:
            if tag[:len_] == inputText.lower():
                return QtGui.QValidator.Intermediate
        return QtGui.QValidator.Invalid

class ExampleWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        [...]
        self.ui_input = QtGui.QLineEdit()
        self.ui_input.setCompleter(self.ui_tag_completer)
        self.ui_input.setPlaceholderText('enter description...')
        self.ui_input.setValidator(TagsValidator(available_tags))
        [...]

    def input_entered(self):
        validator = self.ui_input.validator()
        text = self.ui_input.text()
        state = validator.validate(text, 0)
        if state == QtGui.QValidator.Acceptable:
            self.append_tag(text)