PDA

View Full Version : Trying to overlay widget on a QTreeView item



alketi
29th April 2020, 18:11
I'm trying to align a rectangle over the text portion of a QTreeView item. Calculating the rectangle is a bit complicated because the checkbox indents add up depending on the number of parents, etc.

So to debug this I figured I'd just draw a physical rectangle over the math prediction. However, I'm unable to render a QWidget on top of a tree view item. It never shows up. Any ideas what's wrong or how to overlay a visual over a QTreeView item?

Basically, I want to see something like this, so I can tell where my textRect calc is off.

13428

My attempt below. I'm trying to draw the rectangle in the treeview's mousePressEvent. But, no matter what I do, the overlay widget never appears...


void TreeView::mousePressEvent (QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
QRect textRect = QRect(checkboxX
+ style()->pixelMetric(QStyle::PM_IndicatorWidth)
+ style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing)
+ 30 // color chip and padding
+ 3, // little padding
vrect.y(),
treeItemWidth,
vrect.height());

// Overlay colored widget to see the rectangle
PaintWidget *overlay = new PaintWidget(textRect, this);
overlay->repaint(); // try to force the repaint

}




class PaintWidget : public QWidget
{
Q_OBJECT

public:
explicit PaintWidget(const QRect &paintArea, QWidget *parent=nullptr)
: QWidget(parent), m_area(paintArea)
{
setGeometry(m_area);
QPalette pal = palette();
// set white background
pal.setColor(QPalette::Background, Qt::white);
setPalette(pal);
this->update();
}
~PaintWidget(){};

private:
QRect m_area;
};

d_stranz
29th April 2020, 18:57
You cannot do any on-screen painting anywhere except in a paintEvent().

I think you can probably accomplish what you want with a QStyledItemDelegate. All of the geometry calculations are made for you. Take a look at the Star Delegate (https://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html) example.

You might also be able to do this by adding additional cases to your QAbstractItemModel::data() method to handle the Qt::BackgroundRole.

alketi
29th April 2020, 20:13
Thanks d_stranz, after some more attempts here's the working code.

#include <QPaintEvent>
#include <QPainter>
#include <QDebug>
class PaintWidget : public QWidget
{
Q_OBJECT

public:
explicit PaintWidget(const QRect &paintArea, QWidget *parent=nullptr)
: QWidget(parent), m_area(paintArea)
{
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
}
~PaintWidget(){};

protected:
void paintEvent(QPaintEvent */*event*/) override
{
QPainter(this).fillRect(m_area, {255, 0, 0, 100});
}
private:
QRect m_area;
};


And the calling function I resize the overlay widget to be the entire size of the treeview, but only paint the rectangle of interest.

PaintWidget *overlay = new PaintWidget(textRect, this);
overlay->resize(this->width(), this->height());
overlay->show();