首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QChartView和QScatterSeries夸大了QPointF的标签

QChartView和QScatterSeries夸大了QPointF的标签
EN

Stack Overflow用户
提问于 2018-08-15 10:40:55
回答 1查看 1.7K关注 0票数 2

我有一个QChartView,它显示一些2D点,它们代表每个特定的项目,我想用项目名称来标记每个点,而不是用它的x,y坐标作为默认行为

是否有任何方法实现覆盖创建或呈现标签的功能?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-16 04:16:48

为什么如果不更改Qt源代码就很难做到这一点

  1. QXYSeries系列::setPointLabelsFormat对你没有多大帮助。它确实允许您更改标签的格式,但它的唯一可变部分是点的坐标。
  2. 所有的绘图都是在Qt类的私有部分完成的。以下是整个故事:

标签在私人部分 of QXYSeries (painter->drawText(position, pointLabel);)中绘制:

代码语言:javascript
复制
void QXYSeriesPrivate::drawSeriesPointLabels(QPainter *painter, const QVector<QPointF> &points,
                                             const int offset)
{
    if (points.size() == 0)
        return;
    static const QString xPointTag(QLatin1String("@xPoint"));
    static const QString yPointTag(QLatin1String("@yPoint"));
    const int labelOffset = offset + 2;
    painter->setFont(m_pointLabelsFont);
    painter->setPen(QPen(m_pointLabelsColor));
    QFontMetrics fm(painter->font());
    // m_points is used for the label here as it has the series point information
    // points variable passed is used for positioning because it has the coordinates
    const int pointCount = qMin(points.size(), m_points.size());
    for (int i(0); i < pointCount; i++) {
        QString pointLabel = m_pointLabelsFormat;
        pointLabel.replace(xPointTag, presenter()->numberToString(m_points.at(i).x()));
        pointLabel.replace(yPointTag, presenter()->numberToString(m_points.at(i).y()));
        // Position text in relation to the point
        int pointLabelWidth = fm.width(pointLabel);
        QPointF position(points.at(i));
        position.setX(position.x() - pointLabelWidth / 2);
        position.setY(position.y() - labelOffset);
        painter->drawText(position, pointLabel);
    }
}

drawSeriesPointLabels是从油漆法 of ScatterChartItem调用的(这个类不包含在正式文档中):

代码语言:javascript
复制
void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option)
    Q_UNUSED(widget)
    if (m_series->useOpenGL())
        return;
    QRectF clipRect = QRectF(QPointF(0, 0), domain()->size());
    painter->save();
    painter->setClipRect(clipRect);
    if (m_pointLabelsVisible) {
        if (m_pointLabelsClipping)
            painter->setClipping(true);
        else
            painter->setClipping(false);
        m_series->d_func()->drawSeriesPointLabels(painter, m_points,
                                                  m_series->markerSize() / 2
                                                  + m_series->pen().width());
    }
    painter->restore();
}

反过来,ScatterChartItem是在私人部分 of QScatterSeries中创建的,不能用自定义类替换:

代码语言:javascript
复制
void QScatterSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
{
    Q_Q(QScatterSeries);
    ScatterChartItem *scatter = new ScatterChartItem(q,parent);
    m_item.reset(scatter);
    QAbstractSeriesPrivate::initializeGraphics(parent);
}

你想试试什么

  1. setPointLabelsVisible(false);隐藏原始标签,标签随后将分开绘制。
  2. 子类QChartView并重新实现paintEvent,调用第一个QChartView::paintEvent,然后调用一个自定义函数(比如drawCustomLabels),这是QXYSeriesPrivate::drawSeriesPointLabels的一个修改版本。通过调用drawCustomLabels pass:
代码语言:javascript
复制
- a local painter drawing on the vieport of _MyChartView_,
- the points as returned by `QXYSeries::points`,
- the desired offset.

下面是一个示例,说明了drawCustomLabels的外观:

代码语言:javascript
复制
void MyChartView::drawCustomLabels(QPainter *painter, const QVector<QPointF> &points, const int offset)
{
    if (points.count() == 0)
        return;

    QFontMetrics fm(painter->font());
    const int labelOffset = offset + 2;

    painter->setFont(m_pointLabelsFont); // Use QXYSeries::pointLabelsFont() to access m_pointLabelsFont
    painter->setPen(QPen(m_pointLabelsColor)); // Use QXYSeries::pointLabelsColor() to access m_pointLabelsColor

    for (int n(0); n < points.count(); n++) {
        QString pointLabel = "..."; // Set the desired label for the n-th point of the series
        // Position text in relation to the point
        int pointLabelWidth = fm.width(pointLabel);
        QPointF position(points.at(n));
        position.setX(position.x() - pointLabelWidth / 2);
        position.setY(position.y() - labelOffset);
        painter->drawText(position, pointLabel);
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51857201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档