Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Swap rows QTableWidget
Forum Updated to NodeBB v4.3 + New Features

Swap rows QTableWidget

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 1.8k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Paddle

    I'm working on a QTableWidget :
    3423b0f6-a35b-431d-b444-ccd1ddf029b4-image.png

    I'm trying to make it possible to rearrange the rows with those 'up' 'down' buttons that I just added, or even better by drag and drop.

    I have seen many post about this, and no obvious answers. It is weird it feels like an extremely basic task for a table yet I couldn't find a solution yet.
    I tried the following :

    for (int i = 0; i < columnCount; i++) {
        QTableWidgetItem* sourceItem = ui->workbenchTable->takeItem(rowIndex, i);
        QTableWidgetItem* destinationItem = ui->workbenchTable->takeItem(rowIndex, i + (up ? -1 : 1));
        destinationItem->setBackgroundColor(QColor(150,0,0));
        ui->workbenchTable->setItem(rowIndex, i, destinationItem);
        ui->workbenchTable->setItem(rowIndex, i + (up ? -1 : 1), sourceItem);
    }
    

    But it's not working. I read somewhere that it doesnt work for widgets that have been created with setCellWidget.

    So my questions are :

    • Is QTableWidget the best option here ? I have thought about using QListWidget but I seem to recall that QListWidget can only show static widget. So you can have a button, but can't connect it.
    • How to swap my rows if QTableWidget is the way to go?

    Thanks!

    JonBJ Online
    JonBJ Online
    JonB
    wrote on last edited by
    #3

    @Paddle said in Swap rows QTableWidget:

    I'm trying to make it possible to rearrange the rows

    bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by QTableWidget implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant.

    P 1 Reply Last reply
    0
    • JoeCFDJ JoeCFD

      @Paddle For cellWidgets, you can try to swap them.

      auto cell_widget = your_table->cellWidget(int row, int column); 
      
      your_table->removeCellWidget(int row, int column);
      
      your_table->setCellWidget(int new_row, int new_column, cell_widget);
      

      Note that cell widget is added on top of item. You can not swap items for cell widgets and they have to be swapped separately, I guess.

      P Offline
      P Offline
      Paddle
      wrote on last edited by
      #4

      @JoeCFD said in Swap rows QTableWidget:

      @Paddle For cellWidgets, you can try to swap them.

      auto cell_widget = your_table->cellWidget(int row, int column); 
      
      your_table->removeCellWidget(int row, int column);
      
      your_table->setCellWidget(int new_row, int new_column, cell_widget);
      

      Note that cell widget is added on top of item. You can not swap items for cell widgets and they have to be swapped separately, I guess.

      Thanks. This doesn't work. Apparantly from what I read, when you call removeCellWidget the widget is destroyed. It seems that ownership of the widget cannot be changed.

      JoeCFDJ 1 Reply Last reply
      0
      • P Paddle

        @JoeCFD said in Swap rows QTableWidget:

        @Paddle For cellWidgets, you can try to swap them.

        auto cell_widget = your_table->cellWidget(int row, int column); 
        
        your_table->removeCellWidget(int row, int column);
        
        your_table->setCellWidget(int new_row, int new_column, cell_widget);
        

        Note that cell widget is added on top of item. You can not swap items for cell widgets and they have to be swapped separately, I guess.

        Thanks. This doesn't work. Apparantly from what I read, when you call removeCellWidget the widget is destroyed. It seems that ownership of the widget cannot be changed.

        JoeCFDJ Offline
        JoeCFDJ Offline
        JoeCFD
        wrote on last edited by
        #5

        @Paddle Sorry, I missed that one. Maybe you can create a new one and it does not cost anything, right?

        P 1 Reply Last reply
        0
        • JonBJ JonB

          @Paddle said in Swap rows QTableWidget:

          I'm trying to make it possible to rearrange the rows

          bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by QTableWidget implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant.

          P Offline
          P Offline
          Paddle
          wrote on last edited by
          #6

          @JonB said in Swap rows QTableWidget:

          @Paddle said in Swap rows QTableWidget:

          I'm trying to make it possible to rearrange the rows

          bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by QTableWidget implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant.

          I tried the following but nothing happens. Am I doing something wrong?

          QModelIndex sourceParent = ui->workbenchTable->model()->index(rowIndex, 0);
          QModelIndex destinationParent = ui->workbenchTable->model()->index(rowIndex + (up ? -1 : 1), 0);
          ui->workbenchTable->model()->moveRow(sourceParent, rowIndex, destinationParent, rowIndex + (up ? -1 : 1));
          
          JonBJ 1 Reply Last reply
          0
          • JoeCFDJ JoeCFD

            @Paddle Sorry, I missed that one. Maybe you can create a new one and it does not cost anything, right?

            P Offline
            P Offline
            Paddle
            wrote on last edited by
            #7

            @JoeCFD said in Swap rows QTableWidget:

            @Paddle Sorry, I missed that one. Maybe you can create a new one and it does not cost anything, right?

            No problem of course, your suggestions are very welcome.

            I guess I can recreate the widget yes. I'll try that

            JoeCFDJ 1 Reply Last reply
            0
            • P Paddle

              @JoeCFD said in Swap rows QTableWidget:

              @Paddle Sorry, I missed that one. Maybe you can create a new one and it does not cost anything, right?

              No problem of course, your suggestions are very welcome.

              I guess I can recreate the widget yes. I'll try that

              JoeCFDJ Offline
              JoeCFDJ Offline
              JoeCFD
              wrote on last edited by
              #8

              @Paddle Just curious: these buttons look the same for all rows. Can you simply ignore their swaps. Like:

              for (int i = 0; i < columnCount - 2; i++) {
                  ........
              }
              
              1 Reply Last reply
              0
              • P Paddle

                @JonB said in Swap rows QTableWidget:

                @Paddle said in Swap rows QTableWidget:

                I'm trying to make it possible to rearrange the rows

                bool QAbstractItemModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) allows a row to be moved in a model. Assuming the model used by QTableWidget implements this that should allow re-ordering. I don't know whether the fact there are cell widgets would be relevant.

                I tried the following but nothing happens. Am I doing something wrong?

                QModelIndex sourceParent = ui->workbenchTable->model()->index(rowIndex, 0);
                QModelIndex destinationParent = ui->workbenchTable->model()->index(rowIndex + (up ? -1 : 1), 0);
                ui->workbenchTable->model()->moveRow(sourceParent, rowIndex, destinationParent, rowIndex + (up ? -1 : 1));
                
                JonBJ Online
                JonBJ Online
                JonB
                wrote on last edited by JonB
                #9

                @Paddle said in Swap rows QTableWidget:

                I tried the following but nothing happens. Am I doing something wrong?

                It returns a bool which you can check to see if it worked. Unfortunately I think your code looks correct, so does it return false?. QAbstractItemModel::moveRows() does that and does nothing by default, the derived class has to implement it. If QTableWidget's model does not do that then this is a blind alley.

                P 1 Reply Last reply
                0
                • JonBJ JonB

                  @Paddle said in Swap rows QTableWidget:

                  I tried the following but nothing happens. Am I doing something wrong?

                  It returns a bool which you can check to see if it worked. Unfortunately I think your code looks correct, so does it return false?. QAbstractItemModel::moveRows() does that and does nothing by default, the derived class has to implement it. If QTableWidget's model does not do that then this is a blind alley.

                  P Offline
                  P Offline
                  Paddle
                  wrote on last edited by
                  #10

                  In the end I got it working by creating new widgets and swapping their layout:

                  auto widget = ui->workbenchTable->cellWidget(rowIndex, 0);
                  auto widget2 = ui->workbenchTable->cellWidget(rowIndex + (up ? -1 : 1), 0);
                  
                  auto newWidget = new QWidget(this);
                  newWidget->setObjectName(widget->objectName());
                  newWidget->setLayout(widget->layout());
                  
                  auto newWidget2 = new QWidget(this);
                  newWidget2->setObjectName(widget2->objectName());
                  newWidget2->setLayout(widget2->layout());
                  
                  ui->workbenchTable->removeCellWidget(rowIndex, 0);
                  ui->workbenchTable->removeCellWidget(rowIndex + (up ? -1 : 1), 0);
                  
                  ui->workbenchTable->setCellWidget(rowIndex + (up ? -1 : 1), 0, newWidget);
                  ui->workbenchTable->setCellWidget(rowIndex                , 0, newWidget2);
                  
                  P 1 Reply Last reply
                  0
                  • P Paddle

                    In the end I got it working by creating new widgets and swapping their layout:

                    auto widget = ui->workbenchTable->cellWidget(rowIndex, 0);
                    auto widget2 = ui->workbenchTable->cellWidget(rowIndex + (up ? -1 : 1), 0);
                    
                    auto newWidget = new QWidget(this);
                    newWidget->setObjectName(widget->objectName());
                    newWidget->setLayout(widget->layout());
                    
                    auto newWidget2 = new QWidget(this);
                    newWidget2->setObjectName(widget2->objectName());
                    newWidget2->setLayout(widget2->layout());
                    
                    ui->workbenchTable->removeCellWidget(rowIndex, 0);
                    ui->workbenchTable->removeCellWidget(rowIndex + (up ? -1 : 1), 0);
                    
                    ui->workbenchTable->setCellWidget(rowIndex + (up ? -1 : 1), 0, newWidget);
                    ui->workbenchTable->setCellWidget(rowIndex                , 0, newWidget2);
                    
                    P Offline
                    P Offline
                    Paddle
                    wrote on last edited by
                    #11

                    Sub question: How do you enable drap and drop to move rows ?

                    I used

                    ui->workbenchTable->setDragDropMode(QAbstractItemView::InternalMove);
                    ui->workbenchTable->setSelectionMode(QAbstractItemView::SingleSelection);
                    ui->workbenchTable->setSelectionBehavior(QAbstractItemView::SelectRows);
                    ui->workbenchTable->viewport()->setAcceptDrops(true);
                    ui->workbenchTable->setDropIndicatorShown(true);
                    ui->workbenchTable->setDragEnabled(true);
                    ui->workbenchTable->setAcceptDrops(true);
                    ui->workbenchTable->setDefaultDropAction(Qt::MoveAction);
                    ui->workbenchTable->setDragDropOverwriteMode(false);
                    

                    with this the rows can be dragged, meaning clicking them and dragging moves a rectangle around (the widget itself is not visible in the dragged rectangle).

                    But when I drop nothing happens.

                    How do I connect the signal or catch the drop event? Thanks

                    SGaistS 1 Reply Last reply
                    0
                    • P Paddle

                      Sub question: How do you enable drap and drop to move rows ?

                      I used

                      ui->workbenchTable->setDragDropMode(QAbstractItemView::InternalMove);
                      ui->workbenchTable->setSelectionMode(QAbstractItemView::SingleSelection);
                      ui->workbenchTable->setSelectionBehavior(QAbstractItemView::SelectRows);
                      ui->workbenchTable->viewport()->setAcceptDrops(true);
                      ui->workbenchTable->setDropIndicatorShown(true);
                      ui->workbenchTable->setDragEnabled(true);
                      ui->workbenchTable->setAcceptDrops(true);
                      ui->workbenchTable->setDefaultDropAction(Qt::MoveAction);
                      ui->workbenchTable->setDragDropOverwriteMode(false);
                      

                      with this the rows can be dragged, meaning clicking them and dragging moves a rectangle around (the widget itself is not visible in the dragged rectangle).

                      But when I drop nothing happens.

                      How do I connect the signal or catch the drop event? Thanks

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #12

                      Hi,

                      You should use InternalMove if you plan to only move things around within the same QTableWidget.

                      That said, you really should consider implementing delegates. As explained in the documentation, setCellWidget should only be used to show some static content.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      1

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved