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. [Solved] - QTableView - custom selection indicator (QRubberBand)
Forum Updated to NodeBB v4.3 + New Features

[Solved] - QTableView - custom selection indicator (QRubberBand)

Scheduled Pinned Locked Moved General and Desktop
17 Posts 2 Posters 7.5k Views 1 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.
  • M Offline
    M Offline
    maximus
    wrote on last edited by
    #1

    I have the following QTableView:
    https://www.dropbox.com/s/7rpylmlhgvr62ut/repeatDraw.png

    I would like to implement a way to represent a "repeat" section like in the image above.
    Right now I need to copy the row many times if I want a "repeat" section, what I would like is something like :
    -select a few row
    -click a repeat button and enter a number
    -something in the QtableView representing the repeat is displayed (color, line or whatever)

    Is there something existing in QTableView that I could use to do that?
    I thought of using a QTreeView but it's way overkill for my needs.

    Thanks!


    Free Indoor Cycling Software - https://maximumtrainer.com

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      AFAIK no there's not. You could use e.g. a QRubberBand for the additional "selection" effect

      Hope it helps

      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
      0
      • M Offline
        M Offline
        maximus
        wrote on last edited by
        #3

        Thanks SGaist, I would have never found this usefull class myself!
        With this I think I can achieve what I want!

        So far I got a working example drawing a QRubberBand on every row of my QtableView when I click a "repeat button". It felt a bit hacky to get the QTableView total columns width, maybe i'm missing a function in QTableView? I'm thinking using this code instead of a complex delegate I did to get mouse hover row effect in a QtableView, you guys could implements this easily with a QRubberband :) and add a QTableView row mouseOver effect with stylesheet?

        I will create a custom QRubberBand with a QLabel at the middle right position, and write the number I want there.

        Here is the code:

        @WorkoutCreator::WorkoutCreator(QWidget *parent) : QWidget(parent), ui(new Ui::WorkoutCreator)
        {
        ui->setupUi(this);

        rubberBand = new QRubberBand(QRubberBand::Rectangle, ui->tableView->viewport());
        totalWidthColumms = 0;
        for (int i=0; i<ui->tableView->colorCount(); i++) {
            totalWidthColumms+= ui->tableView->columnWidth(i);
        }
        

        }

        void WorkoutCreator::on_pushButton_repeat_clicked()
        {
        QModelIndexList lstIndex = ui->tableView->selectionModel()->selectedRows();

        if (lstIndex.size() < 1) {
            return;
        }
        
        QRect recFirstSelection(ui->tableView->visualRect(lstIndex.at(0)));
        QRect recLastSelection(ui->tableView->visualRect(lstIndex.at(lstIndex.size()-1)));
        QRect rectCompleteSelection(recFirstSelection.topLeft(), recLastSelection.bottomRight() );
        rectCompleteSelection.setWidth(totalWidthColumms);
        
        rubberBand->move(rectCompleteSelection.topLeft());
        rubberBand->resize(rectCompleteSelection.size());
        

        // rubberBand->setGeometry(rectCompleteSelection);
        rubberBand->show();
        }
        @


        Free Indoor Cycling Software - https://maximumtrainer.com

        1 Reply Last reply
        0
        • M Offline
          M Offline
          maximus
          wrote on last edited by
          #4

          I'm struggling to add text in the QRubberBand paintEvent, I can add a frame around the selection, but for some reason the drawText is not displaying., investigating..

          @void myRubberBand::paintEvent(QPaintEvent *event)
          {
          QRect rec1(event->rect());

          qDebug() << "-----------------\nRECT ORIGINAL" << rec1;
          
          //    QStylePainter painter(this);
          //    QStyleOptionFocusRect option;
          //    option.initFrom(this);
          QStylePainter painter(this);
          QStyleOptionRubberBand option;
          initStyleOption(&option);
          
          
          QPen pen(Qt::red, 2);
          pen.setStyle(Qt::SolidLine);
          //    painter.setBrush(Qt::transparent);
          painter.setPen(pen);
          
          
          /// Find the middle right area
          //    QPoint bottomRight(rec1.bottomRight());
          //    bottomRight.setX(bottomRight.x() + 70);
          //    QRect rectText(rec1.topRight(), bottomRight);
          
          //    qDebug() << "RECT NEW TEXT" <<  rectText;
          
          
          painter.drawText(rec1.topRight(), "abc");
          painter.drawRect(rec1);
          
          
          //    painter.end();
          

          }@


          Free Indoor Cycling Software - https://maximumtrainer.com

          1 Reply Last reply
          0
          • M Offline
            M Offline
            maximus
            wrote on last edited by
            #5

            May be related to this warning: I get a bunch when I launch my program, haven't found the cause :

            @QPaintDevice::metrics: Device has no metric information@

            [Edit: this error what due to bad code here :
            for (int i=0; i<ui->tableView->colorCount(); i++)
            I simply misread colorCount for columnCount


            Free Indoor Cycling Software - https://maximumtrainer.com

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Aren't you drawing the rect above the text ?

              The metrics error is indeed surprising, what OS are you running on ?

              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
              0
              • M Offline
                M Offline
                maximus
                wrote on last edited by
                #7

                Hi,

                I am using Windows 8.1 x64 Enterprise

                I want to draw 2 object ;
                1- Rectangle highlighting with my row(s) selections
                2- Text showing a number at the right side of this rectangle (this one is not showing even if I comment the first object

                You can see my current interface here :
                https://www.dropbox.com/s/puzz9jwx09fwyp9/interface111.png
                What is missing is the black box where I need to draw text

                I updated my current QRubberBand paintEvent up here


                Free Indoor Cycling Software - https://maximumtrainer.com

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Since you are using the event rect which probably is the current QRubberBand geometry, painting on the top right corner makes you paint outside your widget

                  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
                  0
                  • M Offline
                    M Offline
                    maximus
                    wrote on last edited by
                    #9

                    You are right, the text is not painting because it is outside of the rectangle, I tried with this code and I can paint part of the text. Now is there a possibility to draw outside of the event.rect ? If not, I'm thinking maybe add a dummy column at the far right that will serve as place to draw the text. not really clean but could work...

                    Current result with code below :
                    https://www.dropbox.com/s/kumzp59opq9vuhg/currentREsult.png

                    @void myRubberBand::paintEvent(QPaintEvent *event)
                    {
                    QRect rec1(event->rect());

                    // qDebug() << "-----------------\nRECT ORIGINAL" << rec1;
                    QStylePainter painter(this);
                    QStyleOptionRubberBand option;
                    initStyleOption(&option);

                    QPen pen(Qt::red, 2);
                    pen.setStyle(Qt::SolidLine);
                    //    painter.setBrush(Qt::transparent);
                    painter.setPen(pen);
                    
                    /// Find the middle right area of rectangle
                    QPointF pointMiddleRight(rec1.center());
                    pointMiddleRight.setX(pointMiddleRight.x() + 280);
                    painter.drawText(pointMiddleRight, "abc");
                    painter.drawRect(rec1);
                    

                    }@


                    Free Indoor Cycling Software - https://maximumtrainer.com

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      No there's not.

                      Another way to do it, is to add a transparent (mouse event and color transparent) widget over your table view and do all the painting there.

                      Or a second rubber band for the text part that you keep in sync with the original

                      Or make the rubber band larger to also have the space to write the text.

                      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
                      0
                      • M Offline
                        M Offline
                        maximus
                        wrote on last edited by
                        #11

                        All good solutions, working perfectly!, Qt is very flexible
                        Thanks again SGaist


                        Free Indoor Cycling Software - https://maximumtrainer.com

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          maximus
                          wrote on last edited by
                          #12

                          Hey it's me again, I know I dragged this post a lot maybe I should start a new :)

                          Just wondering if something like this would be possible :
                          https://www.dropbox.com/s/xhczf5cg7pu8fxw/editableQRubberBand.png
                          (Editable QComboBox inside the QRubberBand)

                          I know how to draw the text, but not sure the editable QcomboBox is possible? Painting possible, but finding where the signals of the QComboBox is coming from?, maybe giving a unique name to the QComboBox, just tell me if you foresee this as possible before I waste too much time, thanks!


                          Free Indoor Cycling Software - https://maximumtrainer.com

                          1 Reply Last reply
                          0
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Contextual menu ?

                            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
                            0
                            • M Offline
                              M Offline
                              maximus
                              wrote on last edited by
                              #14

                              Contextual menu? This is a right click menu right? IMO this doesn't really feel natural for this function, maybe for removing, copying rows I will use this but for what I need I would like a separate widget that is always displaying inside the QTableView, one widget per Repeat box, like shown in the pic. Not sure it is possible, I can draw it inside the QRubberBand, but it would be static and not usable afterwards. Still trying to use my imagination but I have limited Qt experience :/


                              Free Indoor Cycling Software - https://maximumtrainer.com

                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                Yes and you have a point. Then you could have a QComboBox as member of your QRubberBand and handle its position yourself

                                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
                                0
                                • M Offline
                                  M Offline
                                  maximus
                                  wrote on last edited by
                                  #16

                                  Hi SGaist,
                                  Finally I used the solution of a custom QWidget over the QTableView, I needed a layout and it's easier to manage:

                                  Here is the result interface :
                                  https://www.dropbox.com/s/40osxyrdgxkuaf6/finalUi.png

                                  I post the code in the next post if someone wants to do something similar
                                  <Thread Solved for real now!>

                                  Thank you


                                  Free Indoor Cycling Software - https://maximumtrainer.com

                                  1 Reply Last reply
                                  0
                                  • M Offline
                                    M Offline
                                    maximus
                                    wrote on last edited by
                                    #17

                                    RepeatWidget :
                                    @RepeatWidget::RepeatWidget(QWidget *parent) :
                                    QWidget(parent),
                                    ui(new Ui::RepeatWidget)
                                    {
                                    ui->setupUi(this);

                                    id = 0;
                                    firstRow = 0;
                                    lastRow = 0;
                                    numberRepeat = 0;
                                    

                                    }

                                    void RepeatWidget::on_pushButton_delete_clicked()
                                    {
                                    emit deleteSignal(id);
                                    }

                                    void RepeatWidget::on_comboBox_repeat_currentIndexChanged(const QString &arg1)
                                    {
                                    this->numberRepeat = arg1.toInt();
                                    emit updateSignal(id);
                                    }@

                                    ParentUiClass with QListView:

                                    @WorkoutCreator::~WorkoutCreator()
                                    {
                                    delete ui;
                                    qDeleteAll(lstRepeatWidget);
                                    lstRepeatWidget.clear();
                                    }

                                    WorkoutCreator::WorkoutCreator(QWidget *parent) : QWidget(parent), ui(new Ui::WorkoutCreator)
                                    {
                                    ui->setupUi(this);

                                    [...]

                                    connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
                                            this, SLOT(tableViewSelectionChanged(QItemSelection,QItemSelection)));
                                    
                                    totalWidthColumms = 0;
                                    for (int i=0; i<ui->tableView->colorCount(); i++) {
                                        totalWidthColumms += ui->tableView->columnWidth(i);
                                    }
                                    
                                    ui->pushButton_delete->setEnabled(false);
                                    ui->pushButton_copy->setEnabled(false);
                                    ui->pushButton_repeat->setEnabled(false);
                                    

                                    }

                                    void WorkoutCreator::tableViewSelectionChanged(QItemSelection selected, QItemSelection deselected) {

                                    /// default behavior = disabled
                                    ui->pushButton_delete->setEnabled(false);
                                    ui->pushButton_copy->setEnabled(false);
                                    ui->pushButton_repeat->setEnabled(false);
                                    

                                    // QModelIndexList lstIndex = selected.indexes();
                                    QModelIndexList lstIndex = ui->tableView->selectionModel()->selectedRows();
                                    qDebug() << lstIndex.size();

                                    if (lstIndex.size() < 1) {
                                        return;
                                    }
                                    
                                    ui->pushButton_delete->setEnabled(true);
                                    ui->pushButton_copy->setEnabled(true);
                                    
                                    QModelIndex firstIndex = lstIndex.at(0);
                                    QModelIndex lastIndex = lstIndex.at(lstIndex.size()-1);
                                    
                                    
                                    /// --- Check All overlappign possibilities (see if we can enable repeat button)
                                    foreach (RepeatWidget *wid, lstRepeatWidget) {
                                    
                                        if (firstIndex.row() >= wid->firstRow && firstIndex.row() <= wid->lastRow )  {
                                            qDebug() << "1 REFUSE";
                                            return;
                                        }
                                    
                                        if (lastIndex.row() <= wid->lastRow && lastIndex.row() >= wid->firstRow)  {
                                            qDebug() << "2 REFUSE";
                                            return;
                                        }
                                        if (firstIndex.row() < wid->firstRow && lastIndex.row() > wid->lastRow)  {
                                            qDebug() << "2 REFUSE";
                                            return;
                                        }
                                    }
                                    
                                    ui->pushButton_repeat->setEnabled(true);
                                    

                                    }

                                    void WorkoutCreator::on_pushButton_repeat_clicked()
                                    {

                                    QModelIndexList lstIndex = ui->tableView->selectionModel()->selectedRows();
                                    
                                    if (lstIndex.size() < 1) {
                                        return;
                                    }
                                    
                                    QModelIndex firstIndex = lstIndex.at(0);
                                    QModelIndex lastIndex = lstIndex.at(lstIndex.size()-1);
                                    
                                    QRect recFirstSelection(ui->tableView->visualRect(firstIndex));
                                    QRect recLastSelection(ui->tableView->visualRect(lastIndex));
                                    QRect rectCompleteSelection(recFirstSelection.topLeft(), recLastSelection.bottomRight() );
                                    rectCompleteSelection.setWidth(totalWidthColumms);
                                    
                                    
                                    RepeatWidget *repeatWidget = new RepeatWidget(ui->tableView->viewport());
                                    repeatWidget->id = idRepeatWidget;
                                    repeatWidget->firstRow = firstIndex.row();
                                    repeatWidget->lastRow = lastIndex.row();
                                    repeatWidget->move(rectCompleteSelection.topLeft());
                                    repeatWidget->resize(rectCompleteSelection.size().width() + 190, rectCompleteSelection.size().height());
                                    repeatWidget->show();
                                    
                                    
                                    connect(repeatWidget, SIGNAL(deleteSignal(int)), this, SLOT(deletedRepeatWidget(int)) );
                                    connect(repeatWidget, SIGNAL(updateSignal(int)), this, SLOT(updatedRepeatWidget(int)) );
                                    
                                    
                                    /// Add widget to QList
                                    idRepeatWidget ++;
                                    lstRepeatWidget.append(repeatWidget);
                                    

                                    }

                                    void WorkoutCreator::on_pushButton_add_clicked()
                                    {
                                    intervalModel->insertRow(intervalModel->rowCount());
                                    }

                                    void WorkoutCreator::on_pushButton_copy_clicked()
                                    {

                                    QModelIndexList lstIndex = ui->tableView->selectionModel()->selectedRows();
                                    
                                    foreach (QModelIndex index,  lstIndex) {
                                        qDebug() << "going to copy row:" << index.row();
                                        intervalModel->copyRows(index.row());
                                    }
                                    

                                    }

                                    void WorkoutCreator::on_pushButton_delete_clicked()
                                    {

                                    QModelIndexList lstIndex = ui->tableView->selectionModel()->selectedRows();
                                    
                                    if (lstIndex.size() < 1) {
                                        return;
                                    }
                                    
                                    int startRow = lstIndex.at(0).row();
                                    intervalModel->removeRows(startRow, lstIndex.size(), QModelIndex());
                                    

                                    }

                                    void WorkoutCreator::deletedRepeatWidget(int id) {

                                    qDebug() << "deletedRepeatWidget" << id;
                                    
                                    RepeatWidget *widgetToDelete;
                                    /// Better way to delete without iterating over QList? Array worth it? small data set..
                                    foreach (RepeatWidget *wid, lstRepeatWidget) {
                                        if (wid->id == id) {
                                            wid->setVisible(false);
                                            widgetToDelete = wid;
                                            break;
                                    
                                        }
                                    }
                                    lstRepeatWidget.removeOne(widgetToDelete);
                                    

                                    }

                                    void WorkoutCreator::updatedRepeatWidget(int id) {

                                    qDebug() << "updatedRepeatWidget" << id;
                                    /// TODO: update graph with new values
                                    

                                    }
                                    @


                                    Free Indoor Cycling Software - https://maximumtrainer.com

                                    1 Reply Last reply
                                    0

                                    • Login

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