Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Brainstorm
  4. want to add a graphic to a table
QtWS25 Last Chance

want to add a graphic to a table

Scheduled Pinned Locked Moved Unsolved Brainstorm
14 Posts 6 Posters 2.8k Views
  • 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
    mzimmers
    wrote on 16 Nov 2018, 15:51 last edited by
    #1

    Hi all -

    The app I'm working on contains a QTableView (I'm sure some of you are probably tired of seeing this already):
    0_1542383317408_ui.PNG
    I was thinking about adding a column to show the battery level for each device in the table. It doesn't need to be anything fancy, but a graphic representation might be nice.

    So, if you had to do something like this, what Qt construct(s) would you use to implement it? And, am I going to encounter any complication when I try to incorporate it into a column of my view?

    Thanks...

    1 Reply Last reply
    0
    • V Offline
      V Offline
      VRonin
      wrote on 16 Nov 2018, 16:01 last edited by
      #2

      it should be really easy, it's just about subclassing QStyledItemDelegate and reimplement paint to paint a rectangle with the level of the battery

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      1
      • M Offline
        M Offline
        mzimmers
        wrote on 16 Nov 2018, 16:50 last edited by
        #3

        Heh...the words "Qt," "easy" and "mzimmers" don't often collide in the same sentence.

        I couldn't find an example with the word QStyledItemDelegate, so I've looked at the docs. So, do I create a QModelIndex, and somehow set the delegate onto that?

        Originally I was thinking of using a (readonly) QProgressBar for this, but that's probably overkill. I could just color the background and express the power level as a percentage.

        G 2 Replies Last reply 16 Nov 2018, 17:25
        0
        • M mzimmers
          16 Nov 2018, 16:50

          Heh...the words "Qt," "easy" and "mzimmers" don't often collide in the same sentence.

          I couldn't find an example with the word QStyledItemDelegate, so I've looked at the docs. So, do I create a QModelIndex, and somehow set the delegate onto that?

          Originally I was thinking of using a (readonly) QProgressBar for this, but that's probably overkill. I could just color the background and express the power level as a percentage.

          G Offline
          G Offline
          Gojir4
          wrote on 16 Nov 2018, 17:25 last edited by
          #4

          @mzimmers Hi,

          If you want only to color the background, just return the color from the data() method of your model using the Qt::BackgroundRole, and the percentage value using Qt::DisplayRole.

          1 Reply Last reply
          0
          • M mzimmers
            16 Nov 2018, 16:50

            Heh...the words "Qt," "easy" and "mzimmers" don't often collide in the same sentence.

            I couldn't find an example with the word QStyledItemDelegate, so I've looked at the docs. So, do I create a QModelIndex, and somehow set the delegate onto that?

            Originally I was thinking of using a (readonly) QProgressBar for this, but that's probably overkill. I could just color the background and express the power level as a percentage.

            G Offline
            G Offline
            Gojir4
            wrote on 16 Nov 2018, 18:04 last edited by Gojir4
            #5

            @mzimmers
            Here is an example of reimplementation of a QStyledItemDelegate drawing a progress bar using QStyleOptionProgressBar. It may help you to make your own custom delegate. I think this is pretty close to what you are trying to achieve

            //.h
            #ifndef PROGRESSBARITEMDELEGATE_H
            #define PROGRESSBARITEMDELEGATE_H
            
            #include <QStyledItemDelegate>
            
            class ABSTRACTTASK_SHARED_EXPORT ProgressBarItemDelegate : public QStyledItemDelegate
            {
            public:
                ProgressBarItemDelegate(QObject *parent = 0);
                ~ProgressBarItemDelegate();
            
                QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
            
            protected:
                virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
            
            
            };
            
            #endif // PROGRESSBARITEMDELEGATE_H
            //.cpp
            #include "progressbaritemdelegate.h"
            #include "taskfuturemodel.h"
            
            #include <QAbstractItemView>
            #include <QApplication>
            #include <QDebug>
            #include <QFontMetrics>
            
            ProgressBarItemDelegate::ProgressBarItemDelegate(QObject *parent) :
                QStyledItemDelegate(parent){}
            
            ProgressBarItemDelegate::~ProgressBarItemDelegate() {}
            
            QSize ProgressBarItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
            {
                QSize sizeHint = QStyledItemDelegate::sizeHint(option, index);
                QFont font;
                QFontMetrics fm(font);
                int width = qMax(20, fm.width(index.data(MyModel::ProgressTextRole).toString()));
                //qDebug() << "ProgressBarItemDelegate::sizeHint: " << sizeHint;
                sizeHint.setWidth(width);
                //qDebug() << "ProgressBarItemDelegate::sizeHint updated: " << sizeHint;
            
                return sizeHint;
            }
            
            void ProgressBarItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
            {
            
                //Possible alternative using stylesheet
                //https://stackoverflow.com/questions/10630360/customized-color-on-progressbar-delegate
                if (index.column() == MyModel::COL_PROGRESS_VALUE) {
                    int progress = index.data().toInt();
                    bool failed = progress == -2;
                    int min = 0;
                    //Set undeterminate progress in case of -1 value
                    int max = progress == -1 ? 0 : 100;
                    QString result;
            
                    //Get min & max values from the model data
                    const QAbstractItemModel *model = view->model();
                    if(model){
                        min = index.data(MyModel::ProgressMinRole).toInt();
                        max = index.data(MyModel::ProgressMaxRole).toInt();
                        result = index.data(MyModel::ResultRole).toString();
                    }
                    
                    if(result == "Failed")
                        failed = true;
                    QString progressText = index.data(TaskFutureModel::ProgressTextRole).toString();
            
                    QStyleOptionProgressBar progressBarOption;
                    progressBarOption.rect = option.rect;
                    progressBarOption.minimum = min;
                    progressBarOption.maximum = max;
                    progressBarOption.progress = qMin(progress, progressBarOption.maximum);
            
                    progressBarOption.text = progressText;
                    progressBarOption.textVisible = true;
                    progressBarOption.textAlignment = Qt::AlignCenter;
                    if(failed || result == "Failed"){
                        progressBarOption.palette.setColor(QPalette::Highlight, QColor("red"));
                    } else if(result == "Aborted"){
                        progressBarOption.palette.setColor(QPalette::Highlight, QColor("orange"));
                    } else {
                        progressBarOption.palette.setColor(QPalette::Highlight, QColor("#blue"));
                    }
            
                    if((min == 0 && max == 0 )|| progress == -1){
                        progressBarOption.palette.setColor(QPalette::HighlightedText, QColor("white"));
                        progressBarOption.palette.setColor(QPalette::WindowText, QColor("white"));
                    }
            
                    QApplication::style()->drawControl(QStyle::CE_ProgressBar,
                                                       &progressBarOption, painter);
                } else
                    QStyledItemDelegate::paint(painter, option, index);
            }
            

            Usage:

            ui->tvTasks->setItemDelegateForColumn(<Column_Index>,
                                                      new ProgressBarItemDelegate(myTableView));
            
            M 1 Reply Last reply 16 Nov 2018, 18:23
            2
            • G Gojir4
              16 Nov 2018, 18:04

              @mzimmers
              Here is an example of reimplementation of a QStyledItemDelegate drawing a progress bar using QStyleOptionProgressBar. It may help you to make your own custom delegate. I think this is pretty close to what you are trying to achieve

              //.h
              #ifndef PROGRESSBARITEMDELEGATE_H
              #define PROGRESSBARITEMDELEGATE_H
              
              #include <QStyledItemDelegate>
              
              class ABSTRACTTASK_SHARED_EXPORT ProgressBarItemDelegate : public QStyledItemDelegate
              {
              public:
                  ProgressBarItemDelegate(QObject *parent = 0);
                  ~ProgressBarItemDelegate();
              
                  QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
              
              protected:
                  virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
              
              
              };
              
              #endif // PROGRESSBARITEMDELEGATE_H
              //.cpp
              #include "progressbaritemdelegate.h"
              #include "taskfuturemodel.h"
              
              #include <QAbstractItemView>
              #include <QApplication>
              #include <QDebug>
              #include <QFontMetrics>
              
              ProgressBarItemDelegate::ProgressBarItemDelegate(QObject *parent) :
                  QStyledItemDelegate(parent){}
              
              ProgressBarItemDelegate::~ProgressBarItemDelegate() {}
              
              QSize ProgressBarItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
              {
                  QSize sizeHint = QStyledItemDelegate::sizeHint(option, index);
                  QFont font;
                  QFontMetrics fm(font);
                  int width = qMax(20, fm.width(index.data(MyModel::ProgressTextRole).toString()));
                  //qDebug() << "ProgressBarItemDelegate::sizeHint: " << sizeHint;
                  sizeHint.setWidth(width);
                  //qDebug() << "ProgressBarItemDelegate::sizeHint updated: " << sizeHint;
              
                  return sizeHint;
              }
              
              void ProgressBarItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
              {
              
                  //Possible alternative using stylesheet
                  //https://stackoverflow.com/questions/10630360/customized-color-on-progressbar-delegate
                  if (index.column() == MyModel::COL_PROGRESS_VALUE) {
                      int progress = index.data().toInt();
                      bool failed = progress == -2;
                      int min = 0;
                      //Set undeterminate progress in case of -1 value
                      int max = progress == -1 ? 0 : 100;
                      QString result;
              
                      //Get min & max values from the model data
                      const QAbstractItemModel *model = view->model();
                      if(model){
                          min = index.data(MyModel::ProgressMinRole).toInt();
                          max = index.data(MyModel::ProgressMaxRole).toInt();
                          result = index.data(MyModel::ResultRole).toString();
                      }
                      
                      if(result == "Failed")
                          failed = true;
                      QString progressText = index.data(TaskFutureModel::ProgressTextRole).toString();
              
                      QStyleOptionProgressBar progressBarOption;
                      progressBarOption.rect = option.rect;
                      progressBarOption.minimum = min;
                      progressBarOption.maximum = max;
                      progressBarOption.progress = qMin(progress, progressBarOption.maximum);
              
                      progressBarOption.text = progressText;
                      progressBarOption.textVisible = true;
                      progressBarOption.textAlignment = Qt::AlignCenter;
                      if(failed || result == "Failed"){
                          progressBarOption.palette.setColor(QPalette::Highlight, QColor("red"));
                      } else if(result == "Aborted"){
                          progressBarOption.palette.setColor(QPalette::Highlight, QColor("orange"));
                      } else {
                          progressBarOption.palette.setColor(QPalette::Highlight, QColor("#blue"));
                      }
              
                      if((min == 0 && max == 0 )|| progress == -1){
                          progressBarOption.palette.setColor(QPalette::HighlightedText, QColor("white"));
                          progressBarOption.palette.setColor(QPalette::WindowText, QColor("white"));
                      }
              
                      QApplication::style()->drawControl(QStyle::CE_ProgressBar,
                                                         &progressBarOption, painter);
                  } else
                      QStyledItemDelegate::paint(painter, option, index);
              }
              

              Usage:

              ui->tvTasks->setItemDelegateForColumn(<Column_Index>,
                                                        new ProgressBarItemDelegate(myTableView));
              
              M Offline
              M Offline
              mzimmers
              wrote on 16 Nov 2018, 18:23 last edited by
              #6

              @Gojir4 thank you so much for the example. I've copied your code into my project. I'm getting an error about ABSTRACTTASK_SHARED_EXPORT, and I can't find anything online about that keyword. Can you tell me what it's used for?

              G 1 Reply Last reply 17 Nov 2018, 09:23
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on 16 Nov 2018, 21:02 last edited by
                #7

                Hi,

                It's a custom macro based on the Creating Shared Libraries chapter in Qt's documentation.

                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
                2
                • M Offline
                  M Offline
                  mzimmers
                  wrote on 16 Nov 2018, 21:06 last edited by
                  #8

                  Oh, OK, so I can probably skip it, then?

                  mrjjM 1 Reply Last reply 17 Nov 2018, 13:22
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on 16 Nov 2018, 21:09 last edited by
                    #9

                    If you have that class directly in your application project, yes.

                    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
                    • M mzimmers
                      16 Nov 2018, 18:23

                      @Gojir4 thank you so much for the example. I've copied your code into my project. I'm getting an error about ABSTRACTTASK_SHARED_EXPORT, and I can't find anything online about that keyword. Can you tell me what it's used for?

                      G Offline
                      G Offline
                      Gojir4
                      wrote on 17 Nov 2018, 09:23 last edited by
                      #10

                      @mzimmers Sorry I forgot to remove this keyword from my code.

                      1 Reply Last reply
                      0
                      • M mzimmers
                        16 Nov 2018, 21:06

                        Oh, OK, so I can probably skip it, then?

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on 17 Nov 2018, 13:22 last edited by
                        #11

                        @mzimmers
                        Just as a note.
                        Very small small sample of delegate here.
                        https://forum.qt.io/topic/96545/insert-fill-circle-into-cell-of-qtablewidget/8
                        notice VRonin comment.

                        1 Reply Last reply
                        3
                        • V Offline
                          V Offline
                          VRonin
                          wrote on 19 Nov 2018, 11:22 last edited by
                          #12

                          One more note: This QAbstractItemView *view = qobject_cast<QAbstractItemView *>(parent()); is unsafe as hell. Nothing says the delegate should be a child of the view. in fact you can use the same delegate in multiple views. the correct way to get the model is index.model() without passing from the view

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          kshegunovK G 2 Replies Last reply 19 Nov 2018, 12:40
                          1
                          • V VRonin
                            19 Nov 2018, 11:22

                            One more note: This QAbstractItemView *view = qobject_cast<QAbstractItemView *>(parent()); is unsafe as hell. Nothing says the delegate should be a child of the view. in fact you can use the same delegate in multiple views. the correct way to get the model is index.model() without passing from the view

                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on 19 Nov 2018, 12:40 last edited by
                            #13

                            @VRonin said in want to add a graphic to a table:

                            in fact you can use the same delegate in multiple views.

                            You shouldn't though. There's a warning in the docs about it. I second your parent warning, however, it's quite correct as the view does not take ownership of the delegate.

                            Read and abide by the Qt Code of Conduct

                            1 Reply Last reply
                            1
                            • V VRonin
                              19 Nov 2018, 11:22

                              One more note: This QAbstractItemView *view = qobject_cast<QAbstractItemView *>(parent()); is unsafe as hell. Nothing says the delegate should be a child of the view. in fact you can use the same delegate in multiple views. the correct way to get the model is index.model() without passing from the view

                              G Offline
                              G Offline
                              Gojir4
                              wrote on 19 Nov 2018, 13:44 last edited by
                              #14

                              @VRonin said in want to add a graphic to a table:

                              One more note: This QAbstractItemView *view = qobject_cast<QAbstractItemView *>(parent()); is unsafe as hell. Nothing says the delegate should be a child of the view. in fact you can use the same delegate in multiple views. the correct way to get the model is index.model() without passing from the view

                              Thanks for signaling the issue. I have fixed my sample code above.

                              1 Reply Last reply
                              0

                              4/14

                              16 Nov 2018, 17:25

                              10 unread
                              • Login

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