How to remove extra space around QGraphicsItem and round top corners of Rectangle?
-
Here's what I've in the Bar,
QGraphicsItem
:Bar::Bar(QRectF rect, BarSeries& s, float max, QGraphicsItem *parent) : QGraphicsItem(parent), m_rect(rect), m_series(s), m_max(max){ } QRectF Bar::boundingRect() const { return m_rect; } void Bar::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *){ painter->setRenderHints(QPainter::Antialiasing); painter->setBrush(Qt::black); painter->setPen(Qt::white); painter->translate(0, m_rect.height()); painter->scale(1.0, -1.0); float h1 = m_series.value1 / m_max * m_rect.height(); float h2 = m_series.value2 / m_max * m_rect.height(); auto rect = QRectF(m_rect.left(), 0, m_rect.width(), h1); painter->drawRect(rect); painter->setBrush(Qt::gray); rect = QRectF(m_rect.left(), h1, m_rect.width(), h2); //painter->drawRoundedRect(rect, 0, 5); // tried this to round only top corners painter->drawRect(rect); }
and here's how it looks:
it adds some extra spaces around those rectangles. How to remove those extra spaces and round only top corners of these rectangles? In the BarView,
QGraphicsView
, I add Bar in the scene with these:BarView::BarView(QWidget *parent) : QGraphicsView(parent), m_spacing(5){ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); auto scene = new QGraphicsScene(this); scene->setSceneRect(0,0,200,200); setScene(scene); } void BarView::fit(){ fitInView(scene()->itemsBoundingRect()); centerOn(0,0); } void BarView::resizeEvent(QResizeEvent*){ fit(); } void BarView::addBars(QVector<BarSeries>& series){ scene()->clear(); float max = 0, start = 0, total; for (int i = 0; i < series.size(); i++) { total = series[i].value1 + series[i].value2; if(max < total) max = total; } auto rect = sceneRect(); auto barWidth = rect.width() / series.size() - series.size() * m_spacing - m_spacing; for (int i = 0; i < series.size(); i++) { //auto proportion = (series[i].value1 + series[i].value2) / max * rect.height(); auto barRect = QRectF(start, rect.top(), barWidth, rect.height()); auto bar = new Bar(barRect, series[i], max); scene()->addItem(bar); start += m_spacing + barWidth; } fit(); }
and in the
Window
I've these:Window::Window(QWidget *parent) : QWidget(parent){ auto lay = new QVBoxLayout(this); setLayout(lay); auto combo = new QComboBox(this); combo->addItems(QStringList() << "4" << "5"); barChart = new BarView(this); barChart->setFrameShape(QFrame::Box); lay->addWidget(combo); lay->addWidget(barChart); connect(combo, &QComboBox::currentIndexChanged, this, &Window::onSelectionChanged); combo->setCurrentIndex(1); } Window::~Window(){} void Window::onSelectionChanged(int index){ QVector<BarSeries> series; series.append(BarSeries("S1", 100, 100)); series.append(BarSeries("S2", 200, 100)); series.append(BarSeries("S3", 300, 100)); series.append(BarSeries("S4", 200, 0)); if(index == 1) series.append(BarSeries("S5", 100, 50)); barChart->addBars(series); }
and
BarSeries
is a struct:struct BarSeries{ QString name; float value1; float value2; BarSeries(const QString& name, float value1, float value2){ this->name = name; this->value1 = value1; this->value2 = value2; } };
EDIT
withpainter->setPen(Qt::NoPen);
in Bar the white space between stacked rectangles is removed BUT feels like it still adds some extra space around the whole GraphicsItem. In WPF I used SnapsToDevicePixel, is there anything like that? -
I think you could have also fixed the extra space issue by accounting for the pen width when computing the boundingRect of your Bar QGraphicsItem class; see the note here.
@mchinand, for the pie, I used that technique to put some extra margin around the pie. In this case I, probably, would have to use the
boundingRect
instead ofm_rect
, inpaint
, to get the desired output.