使用 beginMoveColumns 在 QTableView (QAbstractTableModel) 中移动的列不正确?

问题描述

我正在尝试使用 beginMoveColumnsQTableView 中移动单个列,但它在下面的示例中无法正常工作。单元格选择被打乱,列宽不会移动。使用相同的逻辑移动行似乎可以正常工作。我做错了什么?

视频:https://www.screencast.com/t/5UJ0iByZCEE

from PyQt5 import QtWidgets,QtCore,QtGui
import sys
from PyQt5.QtCore import QModelIndex,Qt


class MyTableModel(QtCore.QAbstractTableModel):
    def __init__(self,data=[[]],parent=None):
        super().__init__(parent)
        self.data = data

    def headerData(self,section: int,orientation: Qt.Orientation,role: int):
        if role == QtCore.Qt.displayRole:
            return "Header"

    def columnCount(self,parent=None):
        return len(self.data[0])

    def rowCount(self,parent=None):
        return len(self.data)

    def data(self,index: QModelIndex,role: int):
        if role == QtCore.Qt.displayRole:
            row = index.row()
            col = index.column()
            return str(self.data[row][col])

    def move_column(self,ix,new_ix):
        parent = QtCore.QModelIndex()
        if new_ix > ix:
            target = new_ix + 1
        else:
            target = new_ix
        self.beginMoveColumns(parent,parent,target)

        # Shift column in each row
        for row in self.data:
            row.insert(new_ix,row.pop(ix))

        self.endMoveColumns()

    def move_row(self,new_ix):
        parent = QtCore.QModelIndex()
        if new_ix > ix:
            target = new_ix + 1
        else:
            target = new_ix
        self.beginMoveRows(parent,target)

        # Shift row
        self.data.insert(new_ix,self.data.pop(ix))

        self.endMoveRows()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    data = []
    for i in range(12):
        row = []
        data.append(row)
        for j in range(6):
            row.append(f"R{i}_C{j}")

    model = MyTableModel(data)
    view = QtWidgets.QTableView()
    view.setModel(model)

    view.setColumnWidth(0,50)
    view.setColumnWidth(1,100)

    view.setRowHeight(0,50)
    view.setRowHeight(1,100)

    container = QtWidgets.QWidget()
    layout = QtWidgets.QVBoxLayout()
    container.setLayout(layout)

    layout.addWidget(view)

    button = QtWidgets.QPushButton("Move 1st column right by 1")
    button.clicked.connect(lambda: model.move_column(0,1))
    layout.addWidget(button)

    button = QtWidgets.QPushButton("Move 1st column right by 2")
    button.clicked.connect(lambda: model.move_column(0,2))
    layout.addWidget(button)

    button = QtWidgets.QPushButton("Move 1st row down by 1")
    button.clicked.connect(lambda: model.move_row(0,1))
    layout.addWidget(button)

    button = QtWidgets.QPushButton("Move 1st row down by 2")
    button.clicked.connect(lambda: model.move_row(0,2))
    layout.addWidget(button)

    container.resize(800,800)
    container.show()


    sys.exit(app.exec_())

解决方法

原来这是一个错误,我在这里做了一个错误报告:https://bugreports.qt.io/browse/QTBUG-94503

作为一种解决方法,我只是在列移动时清除单元格选择,并使用此代码段移动列宽

model = view.model()
column_widths = [view.columnWidth(ix) for ix in range(model.columnCount())]
column_widths.insert(new_ix,column_widths.pop(ix))

# Set width of destination column to the width of the source column
for j in range(len(column_widths)):
    view.setColumnWidth(j,column_widths[j])