qt中实现qchart的图例点击操作功能

qt自从提供了qchart之后,可以制作很多图表展示界面,但是qchart的功能有时和实际需求不一样。对于用惯了highcharts的人来说,不能通过图例实现对qchart的操作,感觉很别扭。所以我只好自己开发一个。

具体实现有两个类:TringleLegend和LegendManager,TringleLegend负责画图例和感知点击事件,LegendManager负责管理图例。

TringleLegend的定义:tringlelegend.h

#include <QtCharts/QChartGlobal>
#include <QtWidgets/QGraphicsItem>
#include <QtGui/QFont>
#include <QChart>
#include <QEvent>

QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE

QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE

//因为要使用信号槽机制,所以要继承QObject
class TriggerLegend : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    explicit TriggerLegend(QChart *parent);
    virtual ~TriggerLegend(){}

    //图例图标的颜色
    void setEllipseColor(const QColor &color);
    QColor getEllipseColor();

    //设置图例的文字
    void setText(const QString& text);
    QString getText();

    //设置锚点
    void setAnchor(QPointF point);

    //给图例定义序号
    void setIndex( int idx );
    int getIndex();

    //图例是否处在激活状态
    bool isActived(){return m_bActived;}

    //更新外形结构
    void updateGeometry();

    //获取边框
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
signals:
    //点击信号
    void clicked();
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);

private:
    QString m_text;
    QRectF m_textRect;
    QRectF m_rect;
    QPointF m_anchor;
    QFont m_font;
    QChart *m_chart;
    QColor m_ellipseColor;
    bool m_bActived;
    int m_index;
};

tringlelegend.cpp

#include "triggerlegend.h"


#include <QPainter>
#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>


/**
 * legend组成 shape(10,10)+text(length,10);
 * m_rect width:5+shape.width+10+text.length+5, height:20
 */



TriggerLegend::TriggerLegend(QChart *parent )
    :QGraphicsItem(parent),
    m_chart(parent),
    m_bActived(true),
    m_index(0)
{
}


QRectF TriggerLegend::boundingRect() const
{
    return m_rect;
}

void TriggerLegend::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option)
    Q_UNUSED(widget)
    QRectF boundRect = m_chart->boundingRect();
    //
    QPen pen = painter->pen();
    pen.setWidth(2);
    pen.setColor(QColor(205,205,205));
    painter->setPen(pen);
    QColor shapeColor(205,205,205);
    QColor textColor(205,205,205);
    if( m_bActived )
    {
        shapeColor = m_ellipseColor;
        textColor = QColor(0,0,0);
    }
    painter->setBrush(shapeColor);
    QRectF rect(boundRect.x()/2+5, 10, 10, 10 );
    m_textRect.setLeft(boundRect.x()/2+30);
    painter->drawRect(rect);
    pen = painter->pen();
    pen.setColor(textColor);
    painter->setPen(pen);
    painter->drawText(m_textRect, m_text);
//    qDebug() << this->boundingRect() << m_textRect;
//    painter->drawRect(this->boundingRect());
}

void TriggerLegend::setEllipseColor(const QColor& color)
{
    m_ellipseColor = color;
    show();
}
QColor TriggerLegend::getEllipseColor()
{
    return m_ellipseColor;
}

void TriggerLegend::setText(const QString& text)
{
    m_text = text;
    QFontMetrics metrics(m_font);
    m_textRect = metrics.boundingRect(QRect(20, 5, 200, 150), Qt::AlignLeft, m_text);
    m_textRect.translate(10, 5);

    prepareGeometryChange();
    m_rect = m_textRect.adjusted(-25, -5, 5, 5);
//    qDebug() << "TriggerLegend m_rect:" << m_rect;
//    this->boundingRect()
}


QString TriggerLegend::getText()
{
    return m_text;
}

void TriggerLegend::setAnchor(QPointF point)
{
    m_anchor = point;
}

void TriggerLegend::setIndex( int idx )
{
    m_index = idx;
}

int TriggerLegend::getIndex()
{
    return m_index;
}

void TriggerLegend::updateGeometry()
{
    prepareGeometryChange();
    setPos(m_anchor + QPoint(0, 0));
//    qDebug() << m_anchor;
}


void TriggerLegend::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    if( m_bActived )
    {
        m_bActived = false;
    }
    else
    {
        m_bActived = true;
    }
//    qDebug() << this->m_text;
    updateGeometry();
    emit clicked();
    event->setAccepted(true);
}

void TriggerLegend::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
//    qDebug() << this->m_text;
    event->setAccepted(true);
}
void TriggerLegend::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    event->setAccepted(true);
}

LegendManager的定义:legendManager.h

#include "triggerlegend.h"


class LegendManager : public QObject
{
    Q_OBJECT
public:
    explicit LegendManager(QChart *chart);
    ~LegendManager();

    void InitLegends();
    void FreshLegends();
    void ClearLegends();
public slots:
    void legendClick();

private:
    QChart* m_chart;
    QVector<TriggerLegend*> m_vLegend;
};

LegendManager的实现,legendManager.cpp

#include "legendmanager.h"

#include <QLineSeries>

LegendManager::LegendManager(QChart *chart)
    :m_chart(chart)
{

}

LegendManager::~LegendManager()
{

}


void LegendManager::InitLegends()
{
    for( TriggerLegend* pLegend : m_vLegend )
    {
        pLegend->hide();
        delete pLegend;
    }

    m_vLegend.clear();
    for( int i = 0; i < m_chart->series().size(); ++i )
    {
        const QXYSeries* pSeries = dynamic_cast<QXYSeries*>(m_chart->series().at(i));
        if(pSeries == nullptr )
            continue;

        TriggerLegend *lgd = new TriggerLegend(m_chart);
        lgd->setEllipseColor(pSeries->color());
        if( pSeries->name().isEmpty() )
        {
            lgd->setText(QString("series%1").arg(i));
        }
        else
        {
            lgd->setText(pSeries->name());
        }
        lgd->setZValue(11);
//        qDebug() << "lgd->boundingRect():" << lgd->boundingRect() << pSeries->name();
//        sumWidth += lgd->boundingRect().width();
//        sumHeight = lgd->boundingRect().height();
        connect(lgd,SIGNAL(clicked()),this,SLOT(legendClick()));
        m_vLegend.append(lgd);
    }

    FreshLegends();
}

void LegendManager::FreshLegends()
{
    double rectWidth = m_chart->boundingRect().width();
    double rectHeight = m_chart->boundingRect().height();
    double width;
    double height;
    double left = 0;
//    qDebug() << "m_chart->boundingRect: " << m_chart->boundingRect();
    double sumWidth = 0;//, sumHeight = 0;
    for( TriggerLegend *pLegend : m_vLegend )
    {
        sumWidth += pLegend->boundingRect().width();
    }
    for( TriggerLegend *pLegend : m_vLegend )
    {
        width = pLegend->boundingRect().width();
        height = pLegend->boundingRect().height();
        pLegend->setAnchor(QPointF( (rectWidth-sumWidth)/2 + left,
                                     (rectHeight-height)-10));

        pLegend->updateGeometry();
        pLegend->show();
        left += width + 10;
    }
}


void LegendManager::ClearLegends()
{
    m_vLegend.clear();
}


void LegendManager::legendClick()
{
    TriggerLegend* pLegend = dynamic_cast<TriggerLegend*>(sender());
    int seriesIndex = m_vLegend.indexOf(pLegend);
    if( seriesIndex >= 0 && seriesIndex < m_chart->series().size() )
    {
        if( pLegend->isActived() )
        {
            m_chart->series()[seriesIndex]->show();
        }
        else
        {
            m_chart->series()[seriesIndex]->hide();
        }
    }
}

调用legendManager:

    //m_chart为定义的QChart*
    if( m_pLegendManager == nullptr )
    {
        m_pLegendManager = new LegendManager(m_chart);
    }
    m_pLegendManager->InitLegends();

最后实现效果:

效果图

源码下载路径:ChartTest.rar-C++文档类资源-CSDN文库

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值