Important: Please read the Qt Code of Conduct -

How to drag & drop rows within QTableWidget

  • Hello all,
    I want to drag & drop rows in QTableWidget to change order of rows in the table.
    I want only move whole rows, not overwrite or delete.

    I've tried
    item->setFlags(item->flags() & ~(Qt::ItemIsDropEnabled));
    but it doesn't fully enable to move a row.

    My question is: is it possible to get requested behavior just by correct setting of some flags or is it necessary to inherit and re-implement something?
    Working example is appreciated.

    Thanks in advance,


  • The example below allows you to move rows by calling "setMovable(true)": on the header. Does it give you the behavior you want?

    #include <QtGui>

    int main( int argc, char** argv ) {
    QApplication a( argc, argv );
    QTableWidget table(4,4);
    for(int row =0;row<4;row++)
    for(int col = 0;col<4;col++)
    QTableWidgetItem *item = new QTableWidgetItem(QString("Row%1 Col%2").arg(row).arg(col));
    item->setFlags(item->flags() | Qt::ItemIsSelectable);
    return a.exec();

  • Thank you for reply. but I also need to change the number of moved row. When I drag the row number 5 to first row I also need it to become row number 1 and reorder the rest (not only the row number 5 displayed as first).

  • I'm not sure if that is possible within QTableWidget. If you do it with QTableView and a custom model, you would overwrite the drag / drop stuff in the model.

  • Thank You Gerolf for reply. Can you please give me a hint (or sample code) how to implement it with custom model?

  • If you look inside the "qt docs": there ios a chapter on model view and also on dnd with MVD. I propose you start reading there.

  • I wanted the same functionality for my app. So I searched through internet and didnt find anything. So I had to do it.

    So, you can do it with QTableWidget by using the cellEntered(int,int); then takeItem(row, col) and then setItem()...

    @connect(ui->tableWidget, SIGNAL(cellEntered(int,int)), this, SLOT(cellEnteredSlot(int,int)));@

    @void MainWindow::cellEnteredSlot(int row, int column){

        int colCount=ui->tableWidget->columnCount();
        int rowsel;
        if(ui->tableWidget->currentIndex().row()<row) rowsel=row-1; //down
        else if(ui->tableWidget->currentIndex().row()>row) rowsel=row+1; //up
        else return;
                QList<QTableWidgetItem*> rowItems,rowItems1;
                for (int col = 0; col < colCount; ++col)
                        rowItems << ui->tableWidget->takeItem(row, col);
                        rowItems1 << ui->tableWidget->takeItem(rowsel, col);
                for (int cola = 0; cola < colCount; ++cola)
                        ui->tableWidget->setItem(rowsel, cola,;
                        ui->tableWidget->setItem(row, cola,;


    Warning: I think theres a bug.

    Although it works fine by clicking and holding the left mouse button and moving mouse up or down, it also works with Mouse WHEEL Scroll.

    I have not figure it out yet on how to check if mouse wheel was triggered so not to move selected row.

    The doc says:

    bq. This signal is only emitted when mouseTracking is turned on, or when a mouse button is pressed while moving into an item.

    BUT when you scroll the mouse wheel is not a mouse button press action.

    So I think its a BUG. Should I submit it?

Log in to reply