QTableView:模型中的endMoveRows重置水平标题大小

时间:2018-11-01 16:17:12

标签: c++ drag-and-drop qtableview

我正在尝试对QTableView中的行进行拖放式重新排序。

该操作实际上需要对基础数据进行重新排序,因此对垂直标题行进行重新排序似乎不是一个好的解决方案。

我改为选择底层模型来处理此问题,方法是在其mimeData函数中提供行索引,并在dropMimeData中接受此列表。在dropMimeData函数中,除了移动基础数据之外,我还使用beginMoveRowsendMoveRows可视地移动单个行。这种方法似乎有效,只有一个缺点:我调用endMoveRows时,QTableView的水平标题将其所有节大小重置为默认值。

我是否错过了我需要做的事情,或者这是Qt中的错误(甚至是预期的行为)吗?还有其他方法可以处理拖放的重新排序吗?

以下是显示相同行为的简化代码:

class Model: public QAbstractTableModel
{
public:
    Model():
        m_Items({"A", "B", "C", "D", "E"})
    {
    }

    virtual QVariant data(const QModelIndex & a_Parent, int a_Role) const override
    {
        return QString("%1 - %2").arg(m_Items[a_Parent.row()]).arg(a_Parent.column());
    }

    virtual int rowCount(const QModelIndex & a_Parent) const override
    {
        return m_Items.count();
    }

    virtual int columnCount(const QModelIndex & a_Parent) const override
    {
        return 4;
    }

    void moveNow()
    {
        // Moves the last row as the 3rd row:
        auto count = m_Items.count();
        beginMoveRows(QModelIndex(), count, count, QModelIndex(), 2);
        m_Items.insert(2, m_Items.last());
        m_Items.pop_back();
        endMoveRows();
    }

protected:
    QStringList m_Items;
};

static Model g_Model;

MainWindow::MainWindow(QWidget * parent):
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    // "ui" created by QtCreator, has a "tableView" and a "pushButton"
    ui->setupUi(this);
    ui->tableView->setModel(&g_Model);
    ui->tableView->horizontalHeader()->resizeSection(0, 200);
    ui->tableView->horizontalHeader()->resizeSection(1, 100);
    ui->tableView->horizontalHeader()->resizeSection(2, 50);
    ui->tableView->horizontalHeader()->resizeSection(3, 80);

    connect(ui->pushButton, &QPushButton::clicked,
        [this]()
        {
            // Outputs 200 on first click
            qDebug() << ui->tableView->horizontalHeader()->sectionSize(0);

            g_Model.moveNow();

            // Outputs 100
            qDebug() << ui->tableView->horizontalHeader()->sectionSize(0);
        }
    );
}

1 个答案:

答案 0 :(得分:0)

我发现在移动操作之前调用emit layoutAboutToBeChanged()可以解决此问题:

void moveNow()
{
    emit layoutAboutToBeChanged();
    auto count = m_Items.count();
    beginMoveRows(QModelIndex(), count, count, QModelIndex(), 2);
    m_Items.insert(2, m_Items.last());
    m_Items.pop_back();
    endMoveRows();
}

这似乎与beginMoveRows的文档矛盾,这表明它是调用此函数的替代。此外,在emit layoutChanged()之后必须匹配endMoveRows,否则,列将再次重置。

这一切使我相信这是Qt中的实际错误。