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.7k 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 Offline
    P Offline
    Paddle
    wrote on last edited by Paddle
    #1

    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!

    JoeCFDJ JonBJ 2 Replies Last reply
    1
    • 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!

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

      @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 1 Reply Last reply
      0
      • 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