QCustomPlot Discussion and Comments

is it possible to add multicolor graphReturn to overview

I added graph

ui->widget->addGraph(ui->widget->xAxis, ui->widget->yAxis);
ui->widget->graph(1)->setData(xVector, yVector);

and set color for it:

ui->widget->graph(1)->setPen(QPen(Qt::red));

is it possible to set multi color for graph?
For example red from 0 to 10 and blue from 10 to 30 and ...

As far as I know you can only set the pen (and the color) used to draw the single plots, you cannot set multiple colors/pens to a plot.

That would be a nice feature to be added to QCP.

If you really want this feature quickly, just inherit QCPGraph to your own class like MyQCPGraph and then overload the draw() virtual function. Requires a small amount of effort, but easily done. You could then pass an array containing the pen colours you want for each data point using your new class.

I have done something similar for contouring. I used QCPAbstractPlottable() to draw a contour plot. Each contour line of the plot can have a different colour depending on its contour value if the user chooses.

thank you for your answer sdhengsoft. But I don not understand passing array.
I can create an array and fill with colors but How can I determine color of x-values. For example Array has blue, red, green but in which x values?

Ahhh! Sorry I misunderstood what your values of 0 to 10 were. I thought they were data points 0 through 10. But you mean that these are X values or Y values 0 through 10.

In this case you want to define a function that based on the input value a colour is returned. I do this for contour plotting, but I use a linear colour map. In your case you want a discrete colour map based on input value. So in my code when I want to draw a line I do this:

colourMap = QCPLinearColorMap; // My colour stops are defined as values 0.0 through 1.0.
colourMap.addColorStop( 0.0, Qt::red);
colourMap.addColorStop( 0.1, Qt::blue);
colourMap.addColorStop( 0.3, Qt::green);
...
...
QPen pen;
pen.setColor( colourMap.color( 0.0, 100.0, xValue)); // Set colour range 0 to 100.0.
// Draw somthing.

The code I use for the linear colour map is below. You just need to modify it to do discrete colour changes rather than linear (basically delete some of my code).


class QCPLinearColorMap
{
public:
  QCPLinearColorMap() {}
  ~QCPLinearColorMap() {}

  void addColorStop( const double &value, const QColor &color);
  QColor color( const double &vMin, const double &vMax, const double value);

private:
  struct ColorStop {
    ColorStop( const double &v, const QColor &c) : value( v), color( c) {}
    double value;
    QColor color;
  };

  QList< ColorStop > colorStops_;
};

void QCPLinearColorMap::addColorStop( const double &value, const QColor &color)
{
  colorStops_ << ColorStop( value, color);
}

QColor QCPLinearColorMap::color( const double &vMin, const double &vMax, const double value)
{
  if ( colorStops_.isEmpty()) {
    return QColor();
  }
  if ( colorStops_.count() == 1) {
    return colorStops_[0].color;
  }

  // Normalise value between 0 < x < 1.
  double x = ( value - vMin) / ( vMax - vMin);
  if ( x <= colorStops_.first().value) {
    return colorStops_.first().color;
  }
  if ( x >= colorStops_.last().value) {
    return colorStops_.last().color;
  }

  // Using linear search for closest colour stops rather than mid-point search.
  // It is unlikely there would be a large number of colour stops.
  int i = 0;
  while ( i < colorStops_.count() - 2 && x > colorStops_[i+1].value) {
    ++i;
  }

  // Interpolate between closest colour stops.
  ColorStop &c1 = colorStops_[i];
  ColorStop &c2 = colorStops_[i+1];
  double dx = c2.value - c1.value;
  double r1 = ( c2.value - x) / dx;
  double r2 = ( x - c1.value) / dx;

  int r = r1 * c1.color.red()   + r2 * c2.color.red();
  int g = r1 * c1.color.green() + r2 * c2.color.green();
  int b = r1 * c1.color.blue()  + r2 * c2.color.blue();

  return QColor( r, g, b);
}

I hope this is not too complicated. Have Fun !

Thank you for your answer. I use your code but still all graph has same color. This picture [http://imgur.com/8t0BoQT] shows what I want to do. Do I misuse your code?

I think I'd need to see your overload of the virtual draw() code to figure out why your colours are not changing. Are you able to post the example here?

Actually I can not overloaded draw() function. Just I set QColor (which your color function returns) as parameter in setPen(QPen) function.

Ahh. You need to create your own QCPGraph class and overload the draw() function and do the drawing yourself with the colours you want to use. There is no simple method of setting the multi-colours that I'm aware of.

class MyGraph : public QCPGraph
{
public:
  MyGraph(QCPAxis *keyAxis, QCPAxis *valueAxis) : QCPGraph( keyAxis, valueAxis) {}
  virtual ~MyGraph() {}

protected:
  virtual draw( QCPPainter *painter) {
    // Draw your stuff here based on code in QCPGraph::draw().
  };
}

If I want to plot multiple curves, each curve with different color, what should I do? Thanks.

Have the same task.. can anyone tell, write few line example - what and how exactly should be overloaded draw() function?
here is code I suppose which should be modified somehow..

  
void QCPGraph::draw(QCPPainter *painter) {
....
// draw fill of graph:
  if (mLineStyle != lsNone)
    drawFill(painter, lineData);
  
  // draw line:
  if (mLineStyle == lsImpulse)
    drawImpulsePlot(painter, lineData);
  else if (mLineStyle != lsNone)
    drawLinePlot(painter, lineData); // also step plots can be drawn as a line plot
  
  // draw scatters:
  if (scatterData)
    drawScatterPlot(painter, scatterData);
.... 
}

it isnt the draw function you want to overload, it is the drawFill,drawLinePlot functions. at the top of each function it normally sets the painter's brush and pen. you would want to put that just before it actually calls the painter function to draw something to the canvas.

Does someone have try those solution ? Are they great and not to hard to do?