want to add a graphic to a table
-
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.
-
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.
@mzimmers
Here is an example of reimplementation of a QStyledItemDelegate drawing a progress bar usingQStyleOptionProgressBar
. 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));
-
@mzimmers
Here is an example of reimplementation of a QStyledItemDelegate drawing a progress bar usingQStyleOptionProgressBar
. 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));
-
Hi,
It's a custom macro based on the Creating Shared Libraries chapter in Qt's documentation.
-
If you have that class directly in your application project, yes.
-
@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?
-
@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. -
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 isindex.model()
without passing from the view -
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 isindex.model()
without passing from the view@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.
-
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 isindex.model()
without passing from the view@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 isindex.model()
without passing from the viewThanks for signaling the issue. I have fixed my sample code above.