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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on 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
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on 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
      • mzimmersM Offline
        mzimmersM Offline
        mzimmers
        wrote on 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.

        Gojir4G 2 Replies Last reply
        0
        • mzimmersM mzimmers

          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.

          Gojir4G Offline
          Gojir4G Offline
          Gojir4
          wrote on 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
          • mzimmersM mzimmers

            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.

            Gojir4G Offline
            Gojir4G Offline
            Gojir4
            wrote on 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));
            
            mzimmersM 1 Reply Last reply
            2
            • Gojir4G Gojir4

              @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));
              
              mzimmersM Offline
              mzimmersM Offline
              mzimmers
              wrote on 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?

              Gojir4G 1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on 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
                • mzimmersM Offline
                  mzimmersM Offline
                  mzimmers
                  wrote on last edited by
                  #8

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

                  mrjjM 1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on 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
                    • mzimmersM mzimmers

                      @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?

                      Gojir4G Offline
                      Gojir4G Offline
                      Gojir4
                      wrote on last edited by
                      #10

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

                      1 Reply Last reply
                      0
                      • mzimmersM mzimmers

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

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on 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
                        • VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on 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 Gojir4G 2 Replies Last reply
                          1
                          • VRoninV VRonin

                            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 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
                            • VRoninV VRonin

                              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

                              Gojir4G Offline
                              Gojir4G Offline
                              Gojir4
                              wrote on 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

                              • Login

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