Important: Please read the Qt Code of Conduct -

QTableWidget internal drag animation

  • This is my QTableWidget:

    When I drag a line to move it to a different location, while dragging appears a copy of the line anchored to the mouse cursor. I want to know: can I change the drag 'drop animation? For example, highlight the top edge of the destination row?

    Some hint?

  • Moderators

    you need to reimplement the dragEnter()/dragMove()/dropEvent() of your target widget.
    With the position (taken from the event) you can determine the index at this position using QAbstractItemView::indxAt() and use QAbstractItemView::visualRect() to store the rect. Overload the paintEvent() and do your drawing on top with the rect.

  • This is my attempt:

    void MainWindow::onTracklistMoved(int old_row, int new_row) {
        QTableWidgetItem *itemat = tracklist->itemAt(new_row,0);
        QRect rect = tracklist->visualItemRect(itemat);

    Called on row internal move (note: I need to paint the entire row, not the single cell)

    void DTableWidget::paintEvent(QPaintEvent *event)
        QRect rect = event->rect();
        QPainter painter(this);
        painter.drawText(rect, Qt::AlignCenter,


    • DTableWidget = QTableWidget subclass, with reimplemented dragEnterEvent. dragMoveEvent, dragLeaveEvent, dropEvent, keyPressEvent and paintEvent method.
    Whole DTableWidget class: header and source

    At the app lauch, QtCreator send me these errors:

    QWidget::paintEngine: Should no longer be called
    QPainter::begin: Paint device returned engine == 0, type: 1
    QPainter::setRenderHint: Painter must be active to set rendering hints
    QPainter::setPen: Painter not active
    QPainter::drawRects: Painter not active

    Can you help me?

  • Moderators

    your paintEvent() handler isn't correct. Should look like this:

    void DTableWidget::paintEvent(QPaintEvent *event)
        QTableWidget::paintEvent();  //let it paint the default stuff!
        QPainter painter(this->viewport());  //you need to paint on the viewport
        painter.drawText(rect, Qt::AlignCenter,  "Data");   // you need to take the rect you computed before

    If you need the rect for the whole line you need to take the rect of all sibling items (column count) in the row. QRect has a united() method to "concatenate" 2 rects into 1 surrounding rect.

  • Very well. Last question: how can I remove the copy of the row anchored to the mouse cursor while dragging?

  • [SOLVED]

    To remove the row copy achored to the mouse cursor while dragging, you must reimplement the startDrag() method:

    void DTableWidget::startDrag(Qt::DropActions supportedActions) {
        QModelIndexList indexes = selectedIndexes();
        if (indexes.count() > 0) {
            QMimeData *data = model()->mimeData(indexes);
            if (!data)
            QDrag *drag = new QDrag(this);
            Qt::DropAction defaultDropAction = Qt::IgnoreAction;
            if (defaultDropAction != Qt::IgnoreAction && (supportedActions & defaultDropAction)) 
                defaultDropAction = defaultDropAction;
            else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) 
                defaultDropAction = Qt::CopyAction;

Log in to reply