【问题标题】:How to set a custom point labels format for QLineSeries/QXYSeries?如何为 QLineSeries/QXYSeries 设置自定义点标签格式?
【发布时间】:2019-11-12 23:33:52
【问题描述】:

上下文:我尝试在QChart 上绘制QLineSeries,以便打印值随时间的进展。
因此 X 轴(横坐标)是 QDateTimeAxis,Y 轴(纵坐标)是 QValueAxis

问题:我想显示点标签。但我找不到如何为日期时间设置所需的格式。
默认情况下,标签只能绘制我想要的纵坐标值的整数值。
但是对于横坐标(日期时间)值,它会打印自上一个纪元 (1970-01-01T00:00:00.000) 以来经过的毫秒数。
我想更改日期时间的格式以匹配 "hh:mm:ss"(这是我用来在 QDateTimeAxis 上显示刻度的格式)。

我知道有一个QXYSeries::setPointlabelsFormat() 允许指定格式,但它只接受@xPoint@yPoint 格式标签(您可以在文档中看到)。

  • 您可以在此处找到问题的图片:

如您所见,我可以设置QDateTimeAxis 的格式,但不能在点标签上设置。

产生此输出的代码示例基于提供的here。我只是添加了更多点并取消了//ls->setPointLabelsVisible(true); 行的注释。

问题:有没有办法以自定义格式打印@xPoint 标签(最好匹配QDateTime::toString("hh:mm:ss"))?如果是,如何?

【问题讨论】:

    标签: c++ qt qtcharts


    【解决方案1】:

    QXYSeries 不支持它。您可以通过查看代码从QAbstractSeries 为您的所谓的 QXYDatetimeSeries 派生一个新类,遵循QXYSeries 实现的相同内容。您可能还想更改QXYSeriesPrivate::drawSeriesPointLabels 源代码以支持您的行为。不要忘记将您的更改推送到 Qt git 存储库,以便其他人也可以使用它。

    【讨论】:

    • 感谢您的回答,我已经想到了。但如果可能的话,我想避免它。所以答案是否定的。我不会修改源代码,因为它应该是可移植的并且可以在其他平台上工作(显然不会有我的修改,除非 Qt 接受最终的拉取请求)。我将只画@yPoints。有时间的话,我会重新定义我自己的系列课。
    【解决方案2】:

    正如 Soheim 所指出的,QtCharts 提供的点标签格式对此过于有限。

    如果您不想弄脏 QtCharts 内部,您可以通过另一种方式解决您的问题:自己绘制文本标签。

    QGraphicsObject 派生自定义图形项:

    class PointLabelsItem : public QGraphicsObject
    {
        Q_OBJECT
    public:
        PointLabelsItem(QtCharts::QChart *parent = nullptr);
        virtual QRectF boundingRect() const;
        virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*);
    
    public slots:
        void setRect(const QRectF &area);
        void setAxis(const QAbstractAxis *axis, Qt::Alignment alignment);
        // setter for either source Q*Series or points / point labels
    
    protected:
        QRectF area;
        // const axes*
        // const series* or points/labels
    };
    

    在实现中:

    PointLabelsItem::PointLabelsItem(QtCharts::QChart *parent)
        : QGraphicsObject(parent)
    {
        setZValue(10); // put above series
        connect(parent, &QtCharts::QChart::plotAreaChanged,
            this, &PointLabelsItem::setRect);
    }
    
    QRectF PointLabelsItem::boundingRect() const
    {
        return area;
    }
    
    void PointLabelsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
        // translate between data coordinates and scene coordinates
        // by making use of `area` and the axes' ranges, OR via
        // qobject_cast<QtCharts::QChart>(parent())->mapToPosition()
        // then draw custom point label texts at the corresp. positions
    }
    
    void PointLabelsItem::setRect(const QRectF &newArea)
    {
        area = newArea;
        update();
    }
    
    void setAxis(const QAbstractAxis *axis, Qt::Alignment alignment)
    {
        disconnect(/* old axis member variable */);
        // set corresp. axis member variable here
        connect(axis, &QtCharts::QValueAxis::rangeChanged, this, [this] { update(); });
    }
    

    从外面:

    auto pointLabels = new PointLabelsItem(chart);
    // set axes, series
    

    这是准系统。

    您也可以决定将QGRaphicsTextItems 作为PointLabelsItem 的子代(即,将this 设置为parent 的成员)。这样您就可以启用用户与标签的交互。

    【讨论】:

    • 如果我理解正确的话,这个想法是在QChart 中绘制另一个QGraphicsObject,它将独立绘制标签。听起来不错的解决方法。我猜RangeSelectItem(对于setRect() 的实施范围)是指PointLabelsItem
    • 抱歉,这是一个复制和粘贴错误。我为这个例子修改了我更具体的类。
    猜你喜欢
    • 2020-03-01
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 2022-12-03
    • 2020-12-27
    相关资源
    最近更新 更多