ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Draw Multichart
Posted by Takeshi on Mar-31-2020 22:04
Hi Peter,

Hope you are doing well.
I would like to draw multiple charts, for instance, 10 XYCharts with HLOC layer using Qt C++.
Do I need to define HLOC variables for each of XYCharts? By doing this would have 10 x 4 variables, it is too many.
I am trying to use for loop by passing each set of data to the same HLOC variables but it does not work. My code is as follows:

void DrawMultiChart::drawmultichart()
{
    MultiChart *MCMultiChart = new MultiChart(800, 800);

    for(int i=0;i<10;i++)
    {
        XYChart *MCXYchart = new XYChart(chartwidth,chartheight);
        MCXYchart->setPlotArea(......);

        delete[] MC_highData;
        delete[] MC_lowData;
        delete[] MC_openData;
        delete[] MC_closeData;

        MC_highData = new double[MC_noOfPoints];
        MC_lowData = new double[MC_noOfPoints];
        MC_openData = new double[MC_noOfPoints];
        MC_closeData = new double[MC_noOfPoints];

        MC_openData[i]=......
        MC_highData[i]=......
        MC_lowData[i]=......
        MC_closeData[i]=......

        MCXYchart->addHLOCLayer(DoubleArray(MC_highData, MC_noOfPoints),
                                DoubleArray(MC_lowData, MC_noOfPoints),
                                DoubleArray(MC_openData, MC_noOfPoints),
                                DoubleArray(MC_closeData, MC_noOfPoints),
                                up_candlestickfill, down_candlestickfill);
        MCMultiChart->addChart(.......  , MCXYchart);
     }

     MC_ChartViewer->setChart(MCMultiChart);
     delete MCMultiChart;
}

Please kindly advise and thank you so much in advance.

Best Regards,
Takeshi

  Re: Draw Multichart
Posted by Peter Kwan on Apr-01-2020 01:24
Hi Takeshi,

You can use a loop with 4 variables. Even local variables will work. Would you mind to clarify how would you like to arrange the 10 charts? Are you planning to stack them up, or are you trying to overlay them? Note that the chart background by default is not transparent, so if the charts overlap, the top chart will block the bottom chart.

Also, we suggest you do not delete the MCMultiChart while it is still in the QChartViewer. In some cases, the QChartViewer may need to chart object later, such as if you want to support zoom/scroll or track cursor.

When you delete the MCMultiChart, you would also need to delete the XYChart objects inside to avoid memory leak. In general, if your code uses "new", your code must call "delete" too.

The code would be like:


void DrawMultiChart::drawmultichart()
{
    MultiChart *MCMultiChart = new MultiChart(800, 800);

    for(int i=0;i<10;i++)
    {
        XYChart *MCXYchart = new XYChart(chartwidth,chartheight);
        MCXYchart->setPlotArea(......);

        delete[] MC_highData;
        delete[] MC_lowData;
        delete[] MC_openData;
        delete[] MC_closeData;

        MC_highData = new double[MC_noOfPoints];
        MC_lowData = new double[MC_noOfPoints];
        MC_openData = new double[MC_noOfPoints];
        MC_closeData = new double[MC_noOfPoints];

        for (int j = 0; j < MC_noOfPoints; ++j)
        {
            MC_openData[j]=......
            MC_highData[j]=......
            MC_lowData[j]=......
            MC_closeData[j]=......
        }

        MCXYchart->addHLOCLayer(DoubleArray(MC_highData, MC_noOfPoints),
                                DoubleArray(MC_lowData, MC_noOfPoints),
                                DoubleArray(MC_openData, MC_noOfPoints),
                                DoubleArray(MC_closeData, MC_noOfPoints),
                                up_candlestickfill, down_candlestickfill);
        MCMultiChart->addChart(.......  , MCXYchart);
     }

     MultiChart *oldChart = (MultiChart *)MC_ChartViewer->getChart();
     MC_ChartViewer->setChart(MCMultiChart);

     // delete the oldChart
     if (0 != oldChart)
    {
         for (int i = 0; i < oldChart->getChartCount(); ++i)
             delete oldChart->getChart(i);
         delete oldChart;
    }
}


If the above still does not solve the problem, would you mind to clarify how the 10 charts are positioned in the MultiChart? I am thinking, your MultiChart is 800 pixels tall. If the 10 charts are stacked up, each chart must be quite short. If instead the 10 charts are overlapping, you would need to set the background color to Chart::Transparent in the XYChart constructor.

Regards
Peter Kwan

  Re: Draw Multichart
Posted by Takeshi on Apr-02-2020 22:35
Hi Peter,

Thank you so much for your valuable input, it solves my problem. Actually I just want to stake up the charts, I will modify the size of the MultiChart accordingly.

Do take good care and stay healthy!

Best Regards,
Wei Chuan

  Re: Draw Multichart
Posted by Takeshi on Apr-10-2020 19:17
Attachments:
Hi Peter,

Good day to you, hope you are doing well.
Please kindly advise on how could I resize all XYCharts in a MultiChart if I want to resize the window as shown in the attached image?
Assuming the MultiChart is drawn in drawchart(), the resizemultichart() will be triggered once the window is resized. The error seemingly occurs when running line c->setPlotArea(0,0,chartwidth,chartheight);

My code is as below:

void FinanceDemo::resizemultichart()
{
     MultiChart *oldChart = (MultiChart *)MC_ChartViewer->getChart();
     int height = MCPanel->height()-20;
     int width = MCPanel->width()-20;
     int chartcol = 6;
     int chartrow = 5;
     int chartspace = 5;
     int chartheight = (height-chartspace*chartrow)/(chartrow);
     int chartwidth = (width-chartspace*chartcol)/(chartcol);
     int chartcol_iter = 0;
     int chartrow_iter = 0;

     // delete the oldChart
     if (0 != oldChart)
     {
         MultiChart *MCMultiChart = new MultiChart(MCPanel->width()-10, MCPanel->height()+10);
         for (int i = 0; i < oldChart->getChartCount(); ++i)
         {
             XYChart *c = (XYChart *)oldChart->getChart(i);
             c->setPlotArea(0,0,chartwidth,chartheight); //Error occurs here
             MCMultiChart->addChart(chartcol_iter*(chartwidth+chartspace), chartrow_iter*(chartheight+chartspace), c);
             if (chartcol_iter==chartcol-1){chartcol_iter=0;chartrow_iter++;}
             else chartcol_iter++;
         }
         MC_ChartViewer->setChart(MCMultiChart);
         for (int i = 0; i < oldChart->getChartCount(); ++i)delete oldChart->getChart(i);
         delete oldChart;
     }
}

Thank you so much.

Best Regards,
Takeshi
Image1.png

  Re: Draw Multichart
Posted by Peter Kwan on Apr-10-2020 22:20
Hi Takeshi,

The easiest method to resize a chart is just draw the chart again:

void FinanceDemo::resizemultichart()
{
     drawChart();
}

In the drawChart routine, the charting code should draw the chart according to the MCPanel size.

Hope this can help.

Regards
Peter Kwan

  Re: Draw Multichart
Posted by Takeshi on Apr-10-2020 23:45
Hi Peter,

Thank you for your prompt reply.

As in my drawChart() function, it takes some times to load 30 sets of OHLC data from database. So I am thinking if I can avoid loading data after the first load and just use getchart() to resize the XYCharts. Otherwise, it might take too long to process.

Please let me know if you have any solution. Thank you!

Best Regards,
Takeshi

  Re: Draw Multichart
Posted by Peter Kwan on Apr-12-2020 02:02
Hi Takeshi,

In many of our sample code that needs to redraw rapidly, such as the "Zooming and Scrolling with Track Line" sample code, the code is structured to be like:

// read data into memory
loadData();

// draw chart using data in memory
drawChart();

Then when the chart needs to be redrawn, we just call drawChart. There is no need to load the data again. You may consider this method so that there is no database overhead when you redraw the chart.

https://www.advsofteng.com/doc/cdcpp.htm#zoomscrolltrackqt.htm

In our sample code, we also demonstrates another method to improve user interface responsiveness. Instead of calling drawChart directly, in our sample code, we call "updateViewPort", like:

m_ChartViewer.updateViewPort(true, true);

Then we redraw the chart in the viewPortChanged() event handler. See:

https://www.advsofteng.com/doc/cdcpp.htm#QChartViewer.updateViewPort.htm

Hope this can help.

Regards
Peter Kwan