Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在带有QStandardItemModel的QComboBox上使用QDataWidgetMapper_Python_Pyqt_Pyqt5 - Fatal编程技术网

Python 在带有QStandardItemModel的QComboBox上使用QDataWidgetMapper

Python 在带有QStandardItemModel的QComboBox上使用QDataWidgetMapper,python,pyqt,pyqt5,Python,Pyqt,Pyqt5,我试图通过映射器(QDataWidgetMapper)将数据从QTableModel链接到QComboBox,类似于此处显示的Qt示例: 使用propertyName“currentIndex”或“currentText”,我知道我可以直接映射组合框。但是我想映射一个用户定义的数据 下面是一个小例子:有一个名为CategoryID的对象,还有一个名为ID和Name的类别。combobox具有所有可能的类别,但其索引应根据对象的CategoryID进行更改 以下是我到目前为止所拥有的: 表格模型:

我试图通过映射器(QDataWidgetMapper)将数据从QTableModel链接到QComboBox,类似于此处显示的Qt示例:

使用propertyName“currentIndex”或“currentText”,我知道我可以直接映射组合框。但是我想映射一个用户定义的数据

下面是一个小例子:有一个名为CategoryID的对象,还有一个名为ID和Name的类别。combobox具有所有可能的类别,但其索引应根据对象的CategoryID进行更改

以下是我到目前为止所拥有的:

表格模型:

class ObjectModel(QAbstractTableModel):
    def __init__(self, objects, parent=None):
        super(ObjectModel, self).__init__(parent)
        self.columns = ['name', 'category']
        self.objectList = objects

    def rowCount(self, parent=QModelIndex()):
        return len(self.objectList)

    def columnCount(self, parent=QModelIndex()):
        return len(self.columns)

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.columns[section].title()

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            row = self.objectList[index.row()]
            column_key = self.columns[index.column()]
            return row[column_key]
        else:
            return None

    def setData(self, index, value, role=Qt.EditRole):
        if not index.isValid() or role != Qt.EditRole:
            return False
        if self.objectList:
            column_key = self.columns[index.column()]

            self.objectList[index.row()][column_key] = value
            self.dataChanged.emit(index, index, [])
            return True
        return True
class CategoryModel(QStandardItemModel):
    def __init__(self, categories, parent=None):
        super(CategoryModel, self).__init__(parent)

        self.insertColumns(0, 2, QModelIndex())
        self.insertRows(0, len(categories), QModelIndex())

        self.categoryList = sorted(categories, key=lambda idx: (idx['name']))

        for i, category in enumerate(categories):
            self.setData(self.index(i, 0, QModelIndex()), category["id"], Qt.UserRole)
            self.setData(self.index(i, 1, QModelIndex()), category["name"], Qt.UserRole)

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self.categoryList[index.row()]['name']
        if role == Qt.UserRole:
            return self.categoryList[index.row()]["id"]
class CustomView(QWidget):
    def __init__(self, parent=None):
        super(CustomView, self).__init__(parent)

        self.mapper = QDataWidgetMapper()

        self.spinboxMapperIndex = QSpinBox()
        self.lineEdit = QLineEdit()
        self.comboBox = QComboBox()

        self.spinboxMapperIndex.valueChanged.connect(self.changeMapperIndex)

        self.setupLayout()

    def setModel(self, model):
        self.mapper.setModel(model)
        self.mapper.addMapping(self.lineEdit, 0)
        self.mapper.addMapping(self.comboBox, 1, b'currentData')
        self.mapper.toFirst()

    def changeMapperIndex(self, index):
        self.mapper.setCurrentIndex(index)

    def setupLayout(self):
        layout = QVBoxLayout()
        layout.addWidget(self.spinboxMapperIndex)
        layout.addWidget(self.lineEdit)
        layout.addWidget(self.comboBox)
        self.setLayout(layout)
if __name__ == '__main__':
    app = QApplication(sys.argv)

    categoryList = [
        {
            "id": 23,
            "name": "Flower"
        },
        {
            "id": 456,
            "name": "Furniture"
        }
    ]
    categoryModel = CategoryModel(categoryList)

    objectList = [
        {
            "name": "Lotus",
            "category": 23
        },
        {
            "name": "Table",
            "category": 456
        }
    ]
    objectModel = ObjectModel(objectList)

    view = CustomView()
    view.comboBox.setModel(categoryModel)
    view.setModel(objectModel)
    view.show()

    sys.exit(app.exec_())
StandardItemModel:

class ObjectModel(QAbstractTableModel):
    def __init__(self, objects, parent=None):
        super(ObjectModel, self).__init__(parent)
        self.columns = ['name', 'category']
        self.objectList = objects

    def rowCount(self, parent=QModelIndex()):
        return len(self.objectList)

    def columnCount(self, parent=QModelIndex()):
        return len(self.columns)

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.columns[section].title()

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            row = self.objectList[index.row()]
            column_key = self.columns[index.column()]
            return row[column_key]
        else:
            return None

    def setData(self, index, value, role=Qt.EditRole):
        if not index.isValid() or role != Qt.EditRole:
            return False
        if self.objectList:
            column_key = self.columns[index.column()]

            self.objectList[index.row()][column_key] = value
            self.dataChanged.emit(index, index, [])
            return True
        return True
class CategoryModel(QStandardItemModel):
    def __init__(self, categories, parent=None):
        super(CategoryModel, self).__init__(parent)

        self.insertColumns(0, 2, QModelIndex())
        self.insertRows(0, len(categories), QModelIndex())

        self.categoryList = sorted(categories, key=lambda idx: (idx['name']))

        for i, category in enumerate(categories):
            self.setData(self.index(i, 0, QModelIndex()), category["id"], Qt.UserRole)
            self.setData(self.index(i, 1, QModelIndex()), category["name"], Qt.UserRole)

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self.categoryList[index.row()]['name']
        if role == Qt.UserRole:
            return self.categoryList[index.row()]["id"]
class CustomView(QWidget):
    def __init__(self, parent=None):
        super(CustomView, self).__init__(parent)

        self.mapper = QDataWidgetMapper()

        self.spinboxMapperIndex = QSpinBox()
        self.lineEdit = QLineEdit()
        self.comboBox = QComboBox()

        self.spinboxMapperIndex.valueChanged.connect(self.changeMapperIndex)

        self.setupLayout()

    def setModel(self, model):
        self.mapper.setModel(model)
        self.mapper.addMapping(self.lineEdit, 0)
        self.mapper.addMapping(self.comboBox, 1, b'currentData')
        self.mapper.toFirst()

    def changeMapperIndex(self, index):
        self.mapper.setCurrentIndex(index)

    def setupLayout(self):
        layout = QVBoxLayout()
        layout.addWidget(self.spinboxMapperIndex)
        layout.addWidget(self.lineEdit)
        layout.addWidget(self.comboBox)
        self.setLayout(layout)
if __name__ == '__main__':
    app = QApplication(sys.argv)

    categoryList = [
        {
            "id": 23,
            "name": "Flower"
        },
        {
            "id": 456,
            "name": "Furniture"
        }
    ]
    categoryModel = CategoryModel(categoryList)

    objectList = [
        {
            "name": "Lotus",
            "category": 23
        },
        {
            "name": "Table",
            "category": 456
        }
    ]
    objectModel = ObjectModel(objectList)

    view = CustomView()
    view.comboBox.setModel(categoryModel)
    view.setModel(objectModel)
    view.show()

    sys.exit(app.exec_())
查看:

class ObjectModel(QAbstractTableModel):
    def __init__(self, objects, parent=None):
        super(ObjectModel, self).__init__(parent)
        self.columns = ['name', 'category']
        self.objectList = objects

    def rowCount(self, parent=QModelIndex()):
        return len(self.objectList)

    def columnCount(self, parent=QModelIndex()):
        return len(self.columns)

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.columns[section].title()

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            row = self.objectList[index.row()]
            column_key = self.columns[index.column()]
            return row[column_key]
        else:
            return None

    def setData(self, index, value, role=Qt.EditRole):
        if not index.isValid() or role != Qt.EditRole:
            return False
        if self.objectList:
            column_key = self.columns[index.column()]

            self.objectList[index.row()][column_key] = value
            self.dataChanged.emit(index, index, [])
            return True
        return True
class CategoryModel(QStandardItemModel):
    def __init__(self, categories, parent=None):
        super(CategoryModel, self).__init__(parent)

        self.insertColumns(0, 2, QModelIndex())
        self.insertRows(0, len(categories), QModelIndex())

        self.categoryList = sorted(categories, key=lambda idx: (idx['name']))

        for i, category in enumerate(categories):
            self.setData(self.index(i, 0, QModelIndex()), category["id"], Qt.UserRole)
            self.setData(self.index(i, 1, QModelIndex()), category["name"], Qt.UserRole)

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self.categoryList[index.row()]['name']
        if role == Qt.UserRole:
            return self.categoryList[index.row()]["id"]
class CustomView(QWidget):
    def __init__(self, parent=None):
        super(CustomView, self).__init__(parent)

        self.mapper = QDataWidgetMapper()

        self.spinboxMapperIndex = QSpinBox()
        self.lineEdit = QLineEdit()
        self.comboBox = QComboBox()

        self.spinboxMapperIndex.valueChanged.connect(self.changeMapperIndex)

        self.setupLayout()

    def setModel(self, model):
        self.mapper.setModel(model)
        self.mapper.addMapping(self.lineEdit, 0)
        self.mapper.addMapping(self.comboBox, 1, b'currentData')
        self.mapper.toFirst()

    def changeMapperIndex(self, index):
        self.mapper.setCurrentIndex(index)

    def setupLayout(self):
        layout = QVBoxLayout()
        layout.addWidget(self.spinboxMapperIndex)
        layout.addWidget(self.lineEdit)
        layout.addWidget(self.comboBox)
        self.setLayout(layout)
if __name__ == '__main__':
    app = QApplication(sys.argv)

    categoryList = [
        {
            "id": 23,
            "name": "Flower"
        },
        {
            "id": 456,
            "name": "Furniture"
        }
    ]
    categoryModel = CategoryModel(categoryList)

    objectList = [
        {
            "name": "Lotus",
            "category": 23
        },
        {
            "name": "Table",
            "category": 456
        }
    ]
    objectModel = ObjectModel(objectList)

    view = CustomView()
    view.comboBox.setModel(categoryModel)
    view.setModel(objectModel)
    view.show()

    sys.exit(app.exec_())
Main:

class ObjectModel(QAbstractTableModel):
    def __init__(self, objects, parent=None):
        super(ObjectModel, self).__init__(parent)
        self.columns = ['name', 'category']
        self.objectList = objects

    def rowCount(self, parent=QModelIndex()):
        return len(self.objectList)

    def columnCount(self, parent=QModelIndex()):
        return len(self.columns)

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.columns[section].title()

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            row = self.objectList[index.row()]
            column_key = self.columns[index.column()]
            return row[column_key]
        else:
            return None

    def setData(self, index, value, role=Qt.EditRole):
        if not index.isValid() or role != Qt.EditRole:
            return False
        if self.objectList:
            column_key = self.columns[index.column()]

            self.objectList[index.row()][column_key] = value
            self.dataChanged.emit(index, index, [])
            return True
        return True
class CategoryModel(QStandardItemModel):
    def __init__(self, categories, parent=None):
        super(CategoryModel, self).__init__(parent)

        self.insertColumns(0, 2, QModelIndex())
        self.insertRows(0, len(categories), QModelIndex())

        self.categoryList = sorted(categories, key=lambda idx: (idx['name']))

        for i, category in enumerate(categories):
            self.setData(self.index(i, 0, QModelIndex()), category["id"], Qt.UserRole)
            self.setData(self.index(i, 1, QModelIndex()), category["name"], Qt.UserRole)

    def data(self, index, role=Qt.DisplayRole):
        if role == Qt.DisplayRole or role == Qt.EditRole:
            return self.categoryList[index.row()]['name']
        if role == Qt.UserRole:
            return self.categoryList[index.row()]["id"]
class CustomView(QWidget):
    def __init__(self, parent=None):
        super(CustomView, self).__init__(parent)

        self.mapper = QDataWidgetMapper()

        self.spinboxMapperIndex = QSpinBox()
        self.lineEdit = QLineEdit()
        self.comboBox = QComboBox()

        self.spinboxMapperIndex.valueChanged.connect(self.changeMapperIndex)

        self.setupLayout()

    def setModel(self, model):
        self.mapper.setModel(model)
        self.mapper.addMapping(self.lineEdit, 0)
        self.mapper.addMapping(self.comboBox, 1, b'currentData')
        self.mapper.toFirst()

    def changeMapperIndex(self, index):
        self.mapper.setCurrentIndex(index)

    def setupLayout(self):
        layout = QVBoxLayout()
        layout.addWidget(self.spinboxMapperIndex)
        layout.addWidget(self.lineEdit)
        layout.addWidget(self.comboBox)
        self.setLayout(layout)
if __name__ == '__main__':
    app = QApplication(sys.argv)

    categoryList = [
        {
            "id": 23,
            "name": "Flower"
        },
        {
            "id": 456,
            "name": "Furniture"
        }
    ]
    categoryModel = CategoryModel(categoryList)

    objectList = [
        {
            "name": "Lotus",
            "category": 23
        },
        {
            "name": "Table",
            "category": 456
        }
    ]
    objectModel = ObjectModel(objectList)

    view = CustomView()
    view.comboBox.setModel(categoryModel)
    view.setModel(objectModel)
    view.show()

    sys.exit(app.exec_())
如果我将ID更改为逻辑增量整数,并且在映射过程中使用currentIndex作为propertyName,则这是可行的。但是如果我更改类别列表中的顺序,我希望使用更通用的方法