以柱状图为例,基于QGraphicsItem自定义QtCharts的图例

代码:可以在QT5.9的example中的barchart直接修改。

思路:继承QGraphicsItem和QGraphicsLayoutItem,将marker和label作为图例的最小单位设计出LegendItem;然后用QGraphicsGridLayout为LegendItem进行分行分列排版,添加至QGraphicsWidget的layout中;最后将QGraphicsWidget作为图形item加入到QChart的scence中,并设置原来的legend不可见。

不可行的方法:如果直接用api(chart->legend()->setLayout(QGraphicsGridLayout))会出现崩溃,具体原因我没有深究,毕竟代码是半年前写的。

后续优化:因为涉及到了LegendItem的排版,所以最好还是自定义一个QChartView,方便重写一些resize事件。

图例:customlegend.h 

#ifndef CUSTOMLEGEND_H
#define CUSTOMLEGEND_H

#include <QGraphicsLayoutItem>
#include <QGraphicsItem>
#include <QChartView>	
#include <QChart>
#include <QBarSet>
#include <QBarSeries>

QT_CHARTS_USE_NAMESPACE
class LegendItem : public QGraphicsLayoutItem, public QGraphicsItem
{

public:
	LegendItem(QChart *pChart, QGraphicsLayoutItem *pLayout = nullptr, QGraphicsItem *parent = nullptr);
	~LegendItem();
	// Inherited from QGraphicsLayoutItem
	QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;
	void setLegendItem(QString sTmp, QColor color, int nIndex, QBarSet *pBar, QBarSeries *pSeries);

	// Inherited from QGraphicsItem
	QRectF boundingRect() const override;
	void updateGeometry();
	void setGeometry(const QRectF &geom) override;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
protected:
	void mousePressEvent(QGraphicsSceneMouseEvent *event);
// 	void hoverEnterEvent(QGraphicsSceneMouseEvent *event);
/*	void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);*/
private:
	QString m_sLabel;
	QColor m_color;
	int m_nLine;
	QChart *m_pChart;
	int m_nBarSetIndex;
	QList<QBarSet*> m_lstBarSet;
	QBarSet *m_pBarSet;
	QBarSeries *m_pBarSeries;
	QObject m_object;
};

#endif

 customlegend.cpp

#include "customlegend.h"
#include <QGraphicsSceneResizeEvent>
#include <QGraphicsLayout>
#include <QPainter>
#include <QAbstractSeries>
#include <QDebug>

LegendItem::LegendItem(QChart *pChart, QGraphicsLayoutItem *playout, QGraphicsItem *parent)
	:m_pChart(pChart), QGraphicsLayoutItem(playout), QGraphicsItem(parent)
{
	setGraphicsItem(this);
	setZValue(20);
	setAcceptedMouseButtons(Qt::LeftButton);
	setMaximumWidth(1000);
	m_pBarSeries = NULL;
	m_pBarSet =  NULL;
}

LegendItem::~LegendItem()
{

}


QSizeF LegendItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
	QGraphicsTextItem item(m_sLabel);
	double nWidth = item.boundingRect().width();
	double nHeight = item.boundingRect().height();
	return QSizeF(nWidth + nHeight, nHeight);
}

void LegendItem::setLegendItem(QString sTmp, QColor color, int nIndex, QBarSet *pBar, QBarSeries *pSeries)
{
	m_sLabel = sTmp;
	m_color = color;
	m_nBarSetIndex = nIndex;
	m_pBarSet = pBar;
	m_pBarSeries = pSeries;
	prepareGeometryChange();
}



QRectF LegendItem::boundingRect() const
{
	QGraphicsTextItem item(m_sLabel);
	double nWidth = item.boundingRect().width();
	double nHeight = item.boundingRect().height();
	qreal nShift = m_pChart->boundingRect().width() - m_pChart->legend()->layout()->contentsRect().width();
	return QRectF(QPointF(0, 0), QSizeF(nWidth + nHeight, nHeight));
}

void LegendItem::updateGeometry()
{
	prepareGeometryChange();
}

void LegendItem::setGeometry(const QRectF &geom)
{
	prepareGeometryChange();
	QGraphicsLayoutItem::setGeometry(geom);
	// 	qDebug() << geom;

	setPos(geom.topLeft());
}

void LegendItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= 0*/)
{
	Q_UNUSED(widget);
	Q_UNUSED(option);

	QRectF rect = boundingRect();
	double nHeight = rect.height();
	painter->setRenderHint(QPainter::Antialiasing);
	painter->setPen(Qt::NoPen);
	painter->setBrush(m_color);
	//painter->drawRoundRect(rect.topLeft().x(), rect.topLeft().y(), nHeight, nHeight);
	painter->drawEllipse(rect.topLeft() + QPointF(nHeight / 2, nHeight / 2), nHeight / 2, nHeight / 2);

	painter->setPen(Qt::black);
	painter->drawText(rect.adjusted(nHeight, 0, 0, 0), Qt::AlignCenter, m_sLabel);
}

void LegendItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
	event->setAccepted(true);
	if (this->contains(event->pos()))
	{
		//qDebug() << event->pos() << m_pChart->mapToPosition(this->pos());
	}
	if (!m_pBarSeries || !m_pBarSet)
	{
		return;
	}
	QList<QBarSet *> lstBar = m_pBarSeries->barSets();
	if (lstBar.contains(m_pBarSet))
	{
		qDebug() << m_pBarSeries->children().size() << m_pBarSet->label();
		
		m_pBarSeries->take(m_pBarSet);
		m_color.setAlphaF(0.5);
	}
	else
	{
		m_pBarSeries->insert(m_nBarSetIndex, m_pBarSet);
		
		m_color.setAlphaF(1);
	}
	this->updateGeometry();
}

main.cpp

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Charts module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QLegend>
#include <QtCharts/QBarCategoryAxis>
#include <QGraphicsGridLayout>
#include <QDebug>
#include "customlegend.h"

QT_CHARTS_USE_NAMESPACE

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

//![1]
    QBarSet *set0 = new QBarSet("Jane");
    QBarSet *set1 = new QBarSet("John");
    QBarSet *set2 = new QBarSet("Axel");
    QBarSet *set3 = new QBarSet("Mary");
    QBarSet *set4 = new QBarSet("Samantha");

    *set0 << 1 << 2 << 3 << 4 << 5 << 6;
    *set1 << 5 << 0 << 0 << 4 << 0 << 7;
    *set2 << 3 << 5 << 8 << 13 << 8 << 5;
    *set3 << 5 << 6 << 7 << 3 << 4 << 5;
    *set4 << 9 << 7 << 5 << 3 << 1 << 2;
//![1]

//![2]
    QBarSeries *series = new QBarSeries();
    series->append(set0);
    series->append(set1);
    series->append(set2);
    series->append(set3);
    series->append(set4);

//![2]
	
//![3]
    QChart *chart = new QChart();
    chart->addSeries(series);
    chart->setTitle("Simple barchart example");
    chart->setAnimationOptions(QChart::SeriesAnimations);

	QGraphicsWidget *pLegend = new QGraphicsWidget(0);
	QGraphicsGridLayout *pLegendLayout = new QGraphicsGridLayout(pLegend);
	pLegend->setLayout(pLegendLayout);
	pLegendLayout->setContentsMargins(1, 1, 1, 1);
	QList<QColor> lstColor;
	lstColor << QColor("#919b8e") << QColor("#9a7fd1") << QColor("#DC69AA") << QColor("#e01f54") << QColor("#339ca8") << QColor("2B821D");
//![3]
	QList<QBarSet*> lstBar = series->barSets();
	for (int i = 0; i < lstBar.size(); i++)
	{
		LegendItem *pItem = new LegendItem(chart, chart->layout());
		pItem->setLegendItem(lstBar[i]->label(), lstColor[i], i, lstBar[i], series);
		lstBar[i]->setColor(lstColor[i]);
		pLegendLayout->addItem(pItem, i / 3, i % 3);
	}

//![4]
    QStringList categories;
    categories << "Jan" << "Feb" << "Mar" << "Apr" << "May" << "Jun";
    QBarCategoryAxis *axis = new QBarCategoryAxis();
    axis->append(categories);
    chart->createDefaultAxes();
    chart->setAxisX(axis, series);
//![4]

//![5]
    chart->legend()->setVisible(false);
    chart->legend()->setAlignment(Qt::AlignBottom);
//![5]

//![6]
    QChartView *chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing);
	
	
	
	chartView->chart()->scene()->addItem(pLegend);
	chart->setMargins(QMargins(1, pLegend->minimumHeight(), 1,1));
	pLegend->setMaximumWidth(chart->scene()->width());
	pLegend->setPos(QPointF((chart->scene()->width()) / 2, 0));
	pLegend->setAutoFillBackground(true);


//![6]

//![7]
    QMainWindow window;
    window.setCentralWidget(chartView);
    window.resize(420, 300);
    window.show();
//![7]

    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值