如何使用 QAbstractTableModel 在 QComboBox 中设置多列

How to have multiple columns in a QComboBox with a QAbstractTableModel

我看过类似的问题,但它们针对的是QTableView。这不是使用那个,这只是用于带有自定义 QAbstractTableModel 的下拉列表 (QComboBox),它需要有 2 列。

大更新
(注意:遗留代码已被删除,因为这是解决同一问题的更好方法,而遗留代码非常混乱)。

好的,为了跟上@eyllanesc 的解释,我将其从 QAbstractListModel 更改为 QAbstractTableModel。结果是:

class ModelForComboboxesWithID(QAbstractTableModel):
    """Create our basic model"""

    def __init__(self, program, records):
        super(ModelForComboboxesWithID, self).__init__()
        self._data = records
        self.program = program
        self.path_images = program.PATH_IMAGES

    def rowCount(self, index: int = 0) -> int:
        """The length of the outer list. Structure: [row, row, row]"""
        if not self._data:
            return 0  # Doubt: Do we need to return this if self._data is empty?
        return len(self._data)

    def columnCount(self, index: int = 0) -> int:
        """The length of the sub-list inside the outer list. Meaning that Columns are inside rows
        Structure: [row [column], row [column], row [column]]"""
        if not self._data:
            return 0  # Doubt: Do we need to return this if self._data is empty?
        return len(self._data[0])

    def data(self, index, role=None):
        """return the data on this index as data[row][column]"""
        # 1 - Display data based on its content (this edits the text that you visually see)
        if role == Qt.DisplayRole:
            value = self._data[index.row()][index.column()]
            return value
        # 2 - Tooltip displayed when hovering on it
        elif role == Qt.ToolTipRole:
            return f"ID: {self._data[index.row()][1]}"

我是这样设置的:

def eventFilter(self, target, event: QEvent):
    if event.type() == QEvent.MouseButtonPress:
        if target == self.Buscadorcombo_cliente:
           records = ... # my query to the database
           set_combo_records_with_ids(self.program, target, records)
           target.currentIndexChanged.connect(self.test)

def set_combo_records_with_ids(program, combobox: QComboBox, records):
    """Clear combobox, set model/data and sort it"""
    combobox.clear()
    model = ModelForComboboxesWithID(program, records)
    combobox.setModel(model)
    combobox.model().sort(0, Qt.AscendingOrder)
    combobox.setModelColumn(0)

这个作品的结果近乎完美:

现在我可以通过这种方式获取它的任何数据了。

def test(self, index):
    data_id = self.Buscadorcombo_cliente.model().index(index, 1).data()
    data_name = self.Buscadorcombo_cliente.model().index(index, 0).data()
    print(data_id)
    print(data_name)

您必须将 QTableView 设置为视图:

from PySide2 import QtGui, QtWidgets


def main():
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QWidget()

    combo = QtWidgets.QComboBox()

    model = QtGui.QStandardItemModel(0, 2)
    for i in range(10):
        items = []
        for j in range(model.columnCount()):
            it = QtGui.QStandardItem(f"it-{i}{j}")
            items.append(it)
        model.appendRow(items)

    combo.setModel(model)

    view = QtWidgets.QTableView(
        combo, selectionBehavior=QtWidgets.QAbstractItemView.SelectRows
    )
    combo.setView(view)

    view.verticalHeader().hide()
    view.horizontalHeader().hide()

    header = view.horizontalHeader()
    for i in range(header.count()):
        header.setSectionResizeMode(i, QtWidgets.QHeaderView.Stretch)

    lay = QtWidgets.QVBoxLayout(w)
    lay.addWidget(combo)
    lay.addStretch()
    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()