QTableWidget internal drag animation



  • This is my QTableWidget: http://imgur.com/a/0V4rh

    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.setRenderHint(QPainter::Antialiasing);
        painter.setPen(Qt::black);
        painter.drawText(rect, Qt::AlignCenter,
                          "Data");
        painter.drawRect(rect);
    }
    
    

    Where

    • 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.setRenderHint(QPainter::Antialiasing);
        painter.setPen(Qt::black);
        painter.drawText(rect, Qt::AlignCenter,  "Data");   // you need to take the rect you computed before
        painter.drawRect(rect);
    }
    

    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)
                return;
            QDrag *drag = new QDrag(this);
            drag->setMimeData(data);
            Qt::DropAction defaultDropAction = Qt::IgnoreAction;
            if (defaultDropAction != Qt::IgnoreAction && (supportedActions & defaultDropAction)) 
                defaultDropAction = defaultDropAction;
            else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove) 
                defaultDropAction = Qt::CopyAction;
            drag->exec(defaultDropAction);
        }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.