2

I have an horizontal bar chart with a single QBarSet that looks like this: enter image description here

I want to individually set the color of each bar of the QBarSet. Is there any way this could be done?

I know I could use 3 separate QBarSet instead of one and set the color of each QBarSet individually to achieve what I want. However, I don't want to use this strategy because the label of the bars would appear in a legend at the top of the chart (I want the label of each bar to appear at the left of the bar, like in the snapshot that I provided).

I saw a solution here that explains how to do it on hover events, but I can find a way to modify that solution so that the bars are always colored.

Thanks!

mathlizee
  • 185
  • 2
  • 12

2 Answers2

2

The following method may fail in another configuration since it is highly dependent on what is placed on the chart so if you want an answer to your real problem you must provide an MRE.

Considering the above, the logic is to obtain the items (rectangles) through a filter and set the color:

#include <random>

#include <QApplication>
#include <QtCharts>
QT_CHARTS_USE_NAMESPACE

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

    QBarSet *set0 = new QBarSet("bar1");

    *set0 << 1 << 4 << 3 << 7 << 2 << 5 << 1 << 3 << 3 << 2 << 1 << 6 << 7 << 5;

    QBarSeries *series = new QBarSeries;
    series->append(set0);

    QChart *chart= new QChart;
    w.setChart(chart);
    chart->addSeries(series);

    // filter items
    QList<QGraphicsRectItem *> rect_items;
    for(QGraphicsItem * it : w.items()){
        if(QGraphicsRectItem *rect = qgraphicsitem_cast<QGraphicsRectItem *>(it)){
            if(rect->parentItem() != chart && rect->parentItem()->parentItem() == chart){
                rect_items << rect;
            }
        }
    }

    // change color
    std::random_device dev;
    std::mt19937 rng(dev());
    std::uniform_int_distribution<std::mt19937::result_type> dist255(0, 255);

    for(QGraphicsRectItem * rect : rect_items){
        QColor color(dist255(rng), dist255(rng), dist255(rng));
        rect->setBrush(color);
    }

    w.show();

    return a.exec();
}

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
1

I know I could use 3 separate QBarSet instead of one and set the color of each QBarSet individually to achieve what I want. However, I don't want to use this strategy because the label of the bars would appear in a legend at the top of the chart (I want the label of each bar to appear at the left of the bar, like in the snapshot that I provided).

Having just wrestled with this challenge myself with the same intent, I ended up using a QStackedBarSeries with separate QBarSet instances that use dummy zero values to cause each plotted bar to be a different color, per the chart theme. Obviously, the same trick could be used with manual coloring for each bar set.

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

    QStringList names;
    names << "Parti Conservateur" << "Parti Liberal" << "Parti Vert";
    QList<qreal> counts;
    counts << 41 << 36.3 << 22.7;

    auto series = new QHorizontalStackedBarSeries();
    QList<qreal> dummyCount;
    for(int i = 0; i < names.count(); ++i) {
      auto barSet = new QBarSet(names.at(i));
      // to "trick" the bar chart into different colors, each new group
      // must be in a different value position so replace the previous
      // value with 0 and insert the next one
      if(i > 0) dummyCount.replace(i-1, 0);
      dummyCount << counts.at(i);
      barSet->append(dummyCount);
      series->append(barSet);
    }
    series->setLabelsVisible(true);
    series->setLabelsFormat(QStringLiteral("@value%"));
    series->setLabelsPosition(QAbstractBarSeries::LabelsInsideEnd);

    auto chart = new QChart();
    chart->addSeries(series);
    chart->legend()->hide();

    auto axisY = new QBarCategoryAxis();
    axisY->append(names);
    chart->addAxis(axisY, Qt::AlignLeft);
    series->attachAxis(axisY);
    auto axisX = new QValueAxis();
    chart->addAxis(axisX, Qt::AlignBottom);
    series->attachAxis(axisX);
    axisX->applyNiceNumbers();

    QChartView chartView;
    chartView.setChart(chart);
    chartView.show();

    return a.exec();
}

stacked bar chart with varying colors