Target: I want the class object inherited from QGraphicsItem to be displayed as an icon in QListWidget.
Issue: In the list, the icon is displayed only for the first item.
how it looks
Tried to redefine the function QIconEngine:: pixmap, put a breakpoint on it, but the program does not go into it
Draw so
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setBrush(myColor);
painter->setPen(Qt::black);
painter->drawRect(boundingRect());
painter->drawText(QPointF(w / 2,h / 2),myStr);
}
For this I inherit from QIconEngine
class MyIconEngine : public QIconEngine
{
public:
MyIconEngine(MyItem* item);
// QIconEngine interface
public:
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
QIconEngine *clone() const override;
private:
MyItem* myItem;
};
Its implementation
MyIconEngine::MyIconEngine(MyItem* item): myItem(item)
{}
void MyIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
{
myItem->paint(painter,nullptr,nullptr);
}
QIconEngine *MyIconEngine::clone() const
{
return new MyIconEngine(myItem);
}
Use thus
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QListWidget* lw = new QListWidget();
int w = 45;
int h = 45;
lw->setIconSize(QSize(w,h));
MyItem* i1 = new MyItem(w,h,Qt::red,"red");
MyItem* i2 = new MyItem(w,h,Qt::green,"green");
MyItem* i3 = new MyItem(w,h,Qt::blue,"blue");
MyIconEngine* ie1 = new MyIconEngine(i1);
MyIconEngine* ie2 = new MyIconEngine(i2);
MyIconEngine* ie3 = new MyIconEngine(i3);
QIcon* icon1 = new QIcon(ie1);
QIcon* icon2 = new QIcon(ie2);
QIcon* icon3 = new QIcon(ie3);
QListWidgetItem* lwi1 = new QListWidgetItem(*icon1,i1->Str(),lw);
QListWidgetItem* lwi2 = new QListWidgetItem(*icon2,i2->Str(),lw);
QListWidgetItem* lwi3 = new QListWidgetItem(*icon3,i3->Str(),lw);
lw->show();
return a.exec();
}
MyItem.h
class MyItem : public QGraphicsItem
{
public:
MyItem(int width,int height, const QColor& color,const QString& text);
const QString& Str() const
{
return mySrt;
}
// QGraphicsItem interface
public:
QRectF boundingRect() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
private:
QColor myColor;
int w;
int h;
QString mySrt;
};
MyItem.cpp
MyItem::MyItem(int width, int height, const QColor &color,const QString& text):w(width),h(height),myColor(color),mySrt(text)
{}
QRectF MyItem::boundingRect() const
{
return QRectF(0,0,w,h);
}
void MyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
painter->setBrush(myColor);
painter->setPen(Qt::black);
painter->drawRect(boundingRect());
painter->drawText(QPointF(w / 2,h / 2),mySrt);
}
Cause
You draw the rectangle and the text in the wrong place:
since you do not have information where to draw them.
And you do not have this information, because QGraphicsItem::paint accepts a QStyleOptionGraphicsItem as a second argument, but you pass a
nullptr
in your call:Solution
Create an object of type
QStyleOptionGraphicsItem
, set it up and pass it to thepaint
method. Then use the passed information to draw with thepainter
in the correct places.This will allow you to make further adjustments of how the decoration looks like, depending on the QIcon::Mode and QIcon::State.
Example
Here is a minimal example I have created for you in order to demonstrate how you could implement the proposed solution:
Change your implementation of
MyIconEngine::paint
like this:Change your implementation of
MyItem::paint
like this:I took the liberty to extend the example a bit further than what you have asked in order to show you why using
QStyleOptionGraphicsItem
is the right solution and how you can utilize it to achieve more.This, i.e.
painter->drawText(option->rect, mySrt, QTextOption(Qt::AlignCenter));
, will fix the problem with the text positioning as well.Note: This example is created for demonstration purposes. You might want to make further adjustments to
QStyleOptionGraphicsItem option
in order to make it suit the specific needs of your application.Result
As written, the given example produces the following result: