|
Pie Chart image stuck |
Posted by Guillermo Ganem on May-24-2011 09:08 |
|
Hi Peter,
I have an application that uses a dialog box to get user inputs and initialise pie chart data accordingly.
The code below is the part of the dialog box that is accessed when user presses OK. If I declare
PieChart *pie = new PieChart (560, 600)
right before initialising pie chart data and delete the pointer right after creating the bmp file (pie->makeChart ("piechart.bmp"), it all works perfectly. This means that the user can keep asking for different pie charts at the dialog box, and when he presses OK, the corresponding pie chart file is successfully created every time.
Since I am popping up a window that will have it's own maintenance to process the pie chart (eventually it's own tool bar to Save/Print/Copy-To-Clipboard), I simply converted "pie" into a global scope variable (and delete it only once, when dialog box ends).
To my surprise, that... doesn't work! At first I assumed that was a side effect of the screen bitmap handling, so I just commented all references to it and created a piechart.bmp file without exiting the dialog box procedure.
With this I discovered that the problem is with "pie" being a global-scope variable, because the file has the same problem than when I display to screen: the titles of the pie chart are initialised all right, but the pie's content (pie slices + pie labels) are only right for the very first selection. Whenever the user comes back at dialog box and selects a different option for a pie chart, although the new variables are correctly calculated by the program and fed into "pie" (particulary the pie-setData), the pie slices + pie labels simply stick to the first-time values.
As mentioned, I am now avoiding all calls to the window display routine in order to avoid confusion, and focusing exclusively on generating "piechart.bmp" at the dialog box "OK" code. By simply changing "pie" from being a local variable initialised and deleted each time vs being a global variable initialised and deleted only once, I get this strange behavior.
I have found a "trick" around this using "g_pie" a global pie chart pointer that I initialise every time to "pie" as a local pointer and then use g_pie to the display window routine, but I don't like it, because I am now creating a lot of pie new pointers and never deleting them, so that will eventually go wrong...
Help welcome! Thanks in advance.
FOLLOWS PIE CHART DATA INITIALISATION CODE:
(This code is inside "case IDOK" at DialogBox manager):
......
Code to calculate pie chart variables according to user feedback
.....
Pie structure initialisation:
strcat (chartTitle, "\\n"); strcat (chartTitle, chartSubtitle);
// PieChart *pie= new PieChart (560,500);
pie->setPieSize(275, 320, 160);
pie->addTitle(chartTitle, "arialbd.ttf", 12)->setBackground(0xddccdd);
pie->setData(DoubleArray(chart_data, total_slices), StringArray(chart_labels, total_slices));
pie->set3D(DoubleArray(pie_depths, total_slices));
pie->setStartAngle(150);
pie->setColors(Chart::DataColor, IntArray(pie_colors, total_slices));
pie->setSectorStyle(Chart::LocalGradientShading);
pie->setLabelLayout(0, 1, -1, -1);
pie->setLabelFormat(
"<*block,halign=center, width=90*>" "<*font=arialbi.ttf, size=10*>" "{label}\\n<*font=arialbi.ttf,size=10*> "
"{value|,} ({percent}%)<*/*>");
strcpy(tmpstr, " "); sprintf_thou(tmpstr, pie_subtotal_group1); strcat (tmpstr, " (");
strcpy (outputstr, tmpstr); sprintf (tmpstr, "%-2.2f%%)", 100*pie_subtotal_group1/(pie_subtotal_group1+pie_subtotal_group2));
strcat (outputstr, tmpstr); strcat (outputstr, " : "); strcat (outputstr, sel_banks_str);
while (150-strlen(outputstr)>0) strcat (outputstr, " ");
pie->addText (0, 38, outputstr,
"arial.ttf",10, 0x00ffffff, TopLeft, 0, false)->setBackground (0x00445544);
strcpy(tmpstr, " "); sprintf_thou(tmpstr, pie_subtotal_group2); strcat (tmpstr, " (");
strcpy (outputstr, tmpstr); sprintf (tmpstr, "%-2.2f%%)", 100*pie_subtotal_group2/(pie_subtotal_group1+pie_subtotal_group2));
strcat (outputstr, tmpstr); strcat (outputstr, " : "); strcat (outputstr, ref_banks_str);
while (150-strlen(outputstr)>0) strcat (outputstr, " ");
pie->addText (0, 54, outputstr,
"arial.ttf",10, 0x00ffffff, TopLeft, 0, false)->setBackground (0x00445544);
strcpy(outputstr, " "); sprintf_thou(outputstr, pie_subtotal_group1+pie_subtotal_group2); strcat (outputstr, " (100%)");
strcat (outputstr, " : Total");
while (150-strlen(outputstr)>0) strcat (outputstr, " ");
pie->addText (0, 70, outputstr,
"arial.ttf",10, 0x00ffffff, TopLeft, 0, false)->setBackground (0x00445544);
pie->addText (0, 86, LAST_UPDATE_STR,
"arial.ttf",8, 0x00000000, TopLeft, 0, false)->setBackground (0xff000000);
pie->setExplodeGroup(0,selBankSlices-1, 20);
pie->makeChart("piechart.bmp");
// delete pie;
// g_pie = pie;
// MessageBox(0, chartTitle, _T(outputstr),MB_OK|MB_ICONEXCLAMATION);
//Display Window...
pie_hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"Pie Chart",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 560, 530,
NULL, NULL, g_hInst, NULL);
if(pie_hwnd == NULL) {
MessageBox(0, "Pie Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
// return 0;
}
else {
// PostMessage(pie_hwnd, WM_PAINT, 0, 0);
}
};
break;
}
case IDCANCEL: { //ESC key pressed or 'cancel' button selected
//free up resources
// delete pie; //To delete here when pie can be a global variable!!!!! |
Re: Pie Chart image stuck |
Posted by Peter Kwan on May-24-2011 16:37 |
|
Hi Guillermo,
It does not matter whether pie is a global or local variable. ChartDirector works exactly the same.
In your case, you use different code if pie is a global variable, and that is the cause of the problem. I suggest you change the code to:
... create pie as a global variable and initialize it to 0 ...
delete pie; //delete existing pie before creating new pie to avoid memory leak
pie= new PieChart (560,500);
......
pie->makeChart("piechart.bmp");
//No need to delete pie here, as the pie will either be deleted by the new pie, or
//it will be delete in IDCANCEL. So at any instance, there will only be one pie in memory,
//and there is no memory leak.
Hope this can help.
Regards
Peter Kwan |
Re: Pie Chart image stuck |
Posted by Guillermo Ganem on May-25-2011 23:50 |
|
Hi Peter,
You have an impressive clinical eye... the solution worked perfectly, and now I am displaying not only one pie chart at screen, but several, using an array of pointers that I create/erase as you suggested.
These multiple-charts approach is leading to a new functionality: user scripts to interpret a simple file and save the resulting set of pie charts directly to a file, which the user can then process in Word/Excel with complementary analysis.
I have some questions for you about this:
a) From your list of supported file formats, which one do you recommend to save for a post-process in Word/Excel?
I saw that PNG files are much lighter than BMPs and even seem to have better quality when imported/manipulated into Word, so that looks like a good selection... but I don't know about drawbacks (i.e. will they be supported by all versions of Word/Excel?).
b)I am thinking about getting the destination file name (and probably desired graphics format) from the script and simply append all the graphs to it. Do you have an "append" flag for makeChart, that allows to store one object of the selected format after the other, so that when the user opens the file he can still select each graph separately? Or do I have no choice but creating one file for each graph?
c) Following the logic of reading destination file from script: could it be a .xls or .doc, so that the graphs are saved directly there and the user doesn't have to manually copy/paste when he creates his report? If it's possible, how can I do that?
Thanks again.
Regards,
GGC |
Re: Pie Chart image stuck |
Posted by Peter Kwan on May-26-2011 11:33 |
|
Hi Guillermo,
a) From your list of supported file formats, which one do you recommend to save for a post-process in Word/Excel?
I suggest to use PNG over BMP/JPG/GIF because:
- BMP has much larger file size compared to all graphics format, because BMP is not compressed as per BMP standard, and all other graphics format are compressed. So BMP should not be used.
- GIF only supports 256 colors, while PNG supports true color.
- JPG is good for photographic images, while PNG is good for artificial images. If the chart you create does not use a real photograph as the background image, then PNG should be beter.
I know PNG is supported in Office 2000. I have not tested older versions.
b)I am thinking about getting the destination file name (and probably desired graphics format) from the script and simply append all the graphs to it. Do you have an "append" flag for makeChart, that allows to store one object of the selected format after the other, so that when the user opens the file he can still select each graph separately? Or do I have no choice but creating one file for each graph?
According to PNG, BMP and JPG standard, you cannot store more than one image in the file. Whereas you can store more than one image in GIF, it is usually only used to create "animated GIF", and the user is unlikely to be able to select any specific image in an "animated GIF" (unless the user uses some professional graphical editors to extract the image).
That's why ChartDirector does not have an append option, because it is technically impossible (not permitted by the graphics standard) or not practically useful.
However, if the "destination file" you are referring to are other files (eg. MS Word or Excel), please refer to the MS Word or Excel documentation on how to append images to it.
c) Following the logic of reading destination file from script: could it be a .xls or .doc, so that the graphs are saved directly there and the user doesn't have to manually copy/paste when he creates his report? If it's possible, how can I do that?
Please refer to Microsoft documentation on how to create, store or append an image to MS Word or Excel. For example, see:
http://msdn.microsoft.com/en-us/library/aa200339(office.10).aspx
Hope this can help.
Regards
Peter Kwan |
|