How do you center QGraphicsTextItem in its parent?
-
Right now it centers horizontally:
with these in
PieView
:PieView::PieView(QWidget *parent) : QGraphicsView(parent){ auto scene = new QGraphicsScene(this); setScene(scene); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ellipse = new QGraphicsEllipseItem(); ellipse->setBrush(Qt::white); ellipse->setPen(Qt::NoPen); ellipse->setAcceptHoverEvents(false); text = new QGraphicsTextItem(ellipse); text->setAcceptHoverEvents(false); connect(this, &PieView::mouseOver, this, &PieView::onMouseOver); connect(this, &PieView::mouseLeave, this, &PieView::onMouseLeave); } void PieView::resizeEvent(QResizeEvent*){ fitInView(scene()->itemsBoundingRect(), Qt::KeepAspectRatio); centerOn(0, 0); } void PieView::onMouseOver(PieSeries &s){ text->document()->clear(); auto cursor = QTextCursor(text->document()); QTextBlockFormat blockFormat; QTextCharFormat charFormat; blockFormat.setAlignment(Qt::AlignCenter | Qt::AlignVCenter); charFormat.setForeground(Qt::darkGreen); charFormat.setFontPointSize(16); cursor.setBlockFormat(blockFormat); cursor.setBlockCharFormat(charFormat); cursor.insertText(s.name); charFormat.setForeground(Qt::red); charFormat.setFontPointSize(14); cursor.insertBlock(blockFormat, charFormat); cursor.insertText(QString::number(s.value)); charFormat.setForeground(Qt::black); charFormat.setFontPointSize(12); cursor.insertBlock(blockFormat, charFormat); cursor.insertText(QString::number(s.value / m_total * 100) + "%"); scene()->addItem(ellipse); } void PieView::onMouseLeave(){ scene()->removeItem(ellipse); } void PieView::makePie(QVector<PieSeries>& series){ scene()->clear(); m_total = 0; float startAngle = 0, spanAngle; for (int i = 0; i < series.size(); i++) m_total += series[i].value; QRandomGenerator rand; auto rect = QRectF(0,0, 200,200); for (int i = 0; i < series.size(); i++){ spanAngle = series[i].value / m_total * 360; auto color = QColor::fromRgb(rand.global()->bounded(0,255), rand.global()->bounded(0,255), rand.global()->bounded(0,255)); auto slice = new Slice(startAngle, spanAngle, color, rect, series[i]); scene()->addItem(slice); startAngle += spanAngle; } auto eRect = QRectF(QPoint(sceneRect().center().x() - 75, sceneRect().center().y() - 75), QSize(150,150)); ellipse->setRect(eRect); text->setTextWidth(rect.width()); }
it also moves the whole scene first time. When I first hover over the first slice, those two other slices moved. Here's what is in
Slice
, QGraphicsItem, right now:#define whats16 16 Slice::Slice(float start, float sweep, QColor color, QRectF rect, PieSeries& series) : m_start(start), m_sweep(sweep), m_color(color), m_series(series){ m_realColor = color; m_rect = rect; m_path = QPainterPath(QPointF(m_rect.width() / 2, m_rect.height() / 2)); m_path.arcTo(m_rect, -m_start, -m_sweep); m_path.closeSubpath(); dx = 10 * cos((m_start + m_sweep / 2) * M_PI / 180); dy = 10 * sin((m_start + m_sweep / 2) * M_PI / 180); float dimension = m_rect.width() + 2 * 20; m_boundingRect = QRectF(-20, -20, dimension, dimension); setAcceptHoverEvents(true); } QRectF Slice::boundingRect() const { return m_boundingRect; } QPainterPath Slice::shape() const { return m_path;} void Slice::hoverEnterEvent(QGraphicsSceneHoverEvent*){ m_color = Qt::gray; moveBy(dx, dy); auto view = static_cast<PieView*>(scene()->parent()); emit view->mouseOver(m_series); } void Slice::hoverLeaveEvent(QGraphicsSceneHoverEvent*){ m_color = m_realColor; moveBy(-dx, -dy); auto view = static_cast<PieView*>(scene()->parent()); emit view->mouseLeave(); } void Slice::paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*){ painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush(m_color); painter->drawPie(m_rect, whats16 * -m_start, whats16 * -m_sweep); }
in main window, I've a QComboBox and PieView in a QVboxLayout:
Window::Window(QWidget *parent) : QWidget(parent){ auto combo = new QComboBox(this); combo->addItems(QStringList() << "6" << "3"); pie = new PieView(this); pie->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); auto lay = new QVBoxLayout(this); lay->setContentsMargins(0,0,0,0); lay->addWidget(combo); lay->addWidget(pie); setLayout(lay); connect(combo, &QComboBox::currentIndexChanged, this, &Window::oSelectionChanged); combo->setCurrentIndex(1); } void Window::oSelectionChanged(int index){ QVector<PieSeries> series; if(index == 0){ series.append(PieSeries("Series 1", 100)); series.append(PieSeries("Series 2", 200)); series.append(PieSeries("Series 3", 300)); series.append(PieSeries("Series 4", 150)); series.append(PieSeries("Series 5", 225)); series.append(PieSeries("Series 6", 275)); } else if(index == 1){ series.append(PieSeries("Series 2", 200)); series.append(PieSeries("Series 3", 300)); series.append(PieSeries("Series 4", 150)); } pie->makePie(series); }
PieSeries
is a struct with these:struct PieSeries{ QString name; float value; PieSeries(QString name, float value){ this->name = name; this->value = value; } };
-
For the text alignment, this
setY
... text->setY(ellipse->boundingRect().center().y() - text->boundingRect().height()/2); scene()->addItem(ellipse);
in
void PieView::onMouseOver(PieSeries &s)
works:Still couldn't figure out why the remaining slices moves once or more when I first start hovering over slices