wxIshiko / wxCharts

A library to create charts in wxWidgets applications
https://www.wxishiko.com/wxCharts/
MIT License
131 stars 51 forks source link

StackedColumnChart can't take more than 3 datasets #165

Open gismowdd opened 4 years ago

gismowdd commented 4 years ago

Compiled using mingw32 with wxWidgets-3.1.3 on Windows 10 . When i add more than 3 datasets it compiles but at runtime I get the error:

sharedptr.h(85):assert "m_ref!=_null" failed in operator().

I can run any combination of 3 of the 4 datasets just fine using the sample code.

Kvaz1r commented 4 years ago

That's because default theme has only 3 sets of predefined datasets options value.

So if you going to use more than 3 datasets just update default theme:

    wxChartsDatasetTheme* datasettheme = new wxChartsDatasetTheme();
    datasettheme->SetStackedColumnChartDatasetOptions(wxStackedColumnChartDatasetOptions(
        wxChartsPenOptions(*wxBLACK, 2),
        wxChartsBrushOptions(*wxRED)
    ));
    wxChartsDefaultTheme->SetDatasetTheme(wxChartsDatasetId::CreateImplicitId(3), wxSharedPtr<wxChartsDatasetTheme>(datasettheme));

where Id is index of dataset.

helha54 commented 3 years ago

I tried to modifie the default theme but that did not work. I have the same issues with the wxLinechart wher i need 10 datasets insteed of the three. Can You please explain a little deeper how to update the chartsDefault, because it did'nt work the right way for me.

Kvaz1r commented 3 years ago

The code above should worked for wxLineChartCtrl too. Try to change wxlinechartframe.cpp from sample with this code:

#include "wxlinechartframe.h"
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/charts/wxcharts.h>
#include <random>

wxLineChartFrame::wxLineChartFrame(const wxString& title)
    : wxFrame(NULL, wxID_ANY, title)
{
    // Create a top-level panel to hold all the contents of the frame
    wxPanel* panel = new wxPanel(this, wxID_ANY);

    // Create the data for the line chart widget
    wxVector<wxString> labels;
    labels.push_back("January");
    labels.push_back("February");
    labels.push_back("March");
    labels.push_back("April");
    labels.push_back("May");
    labels.push_back("June");
    labels.push_back("July");
    wxChartsCategoricalData::ptr chartData = wxChartsCategoricalData::make_shared(labels);

    std::ranlux48 rng(std::random_device{}());
    auto dist = std::uniform_real_distribution<double>(0, 100);
    auto dist2 = std::uniform_int_distribution<unsigned long>(0, 3000000);

    wxVector<wxVector<wxDouble>> points;

    for (std::size_t i = 0; i < 10; i++)
    {
        wxVector<wxDouble> vec(labels.size());
        for (std::size_t j = 0; j < labels.size(); j++)
        {
            vec[j] = dist(rng);//generate random data
        }
        points.push_back(vec);
        // update default theme for dataset 
        if (i >= 3)
        {
            wxColor color = dist2(rng); //generate random color

            wxChartsDatasetTheme* datasettheme = new wxChartsDatasetTheme();
            datasettheme->SetLineChartDatasetOptions(wxLineChartDatasetOptions(
                color,
                color,
                wxTransparentColor
            ));
            wxChartsDefaultTheme->SetDatasetTheme(wxChartsDatasetId::CreateImplicitId(i), wxSharedPtr<wxChartsDatasetTheme>(datasettheme));
        }
    }

    for (std::size_t i = 0; i < points.size(); i++)
    {
        wxChartsDoubleDataset::ptr dataset(
            new wxChartsDoubleDataset(
                wxString::Format("%d dataset", i), points[i]));
        chartData->AddDataset(dataset);
    }

    // Create the line chart widget from the constructed data
    wxLineChartCtrl* lineChartCtrl = new wxLineChartCtrl(panel, wxID_ANY, chartData,
        wxCHARTSLINETYPE_STRAIGHT, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);

    // Create the legend widget
    wxChartsLegendData legendData(chartData->GetDatasets());
    wxChartsLegendCtrl* legendCtrl = new wxChartsLegendCtrl(panel, wxID_ANY, legendData,
        wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);

    // Set up the sizer for the panel
    wxBoxSizer* panelSizer = new wxBoxSizer(wxHORIZONTAL);
    panelSizer->Add(lineChartCtrl, 1, wxEXPAND);
    panelSizer->Add(legendCtrl, 1, wxEXPAND);
    panel->SetSizer(panelSizer);

    // Set up the sizer for the frame
    wxBoxSizer* topSizer = new wxBoxSizer(wxHORIZONTAL);
    topSizer->Add(panel, 1, wxEXPAND);
    SetSizerAndFit(topSizer);
}
helha54 commented 3 years ago

Thank You for the help. I can see all 10 datasets. Now I have only to make the fill for the fist two lines disappear.

helha54 commented 3 years ago

I have one more question where can I find documentation about ChartsDefaultTheme

Kvaz1r commented 3 years ago

Now I have only to make the fill for the fist two lines disappear.

            auto options = wxChartsDefaultTheme->GetDatasetTheme(
                wxChartsDatasetId::CreateImplicitId(i))->GetLineChartDatasetOptions();

            wxChartsDefaultTheme->GetDatasetTheme(
                wxChartsDatasetId::CreateImplicitId(i))->SetLineChartDatasetOptions(wxLineChartDatasetOptions(
                options->GetLineColor(),
                options->GetLineColor(),
                wxTransparentColor
            ));

I have one more question where can I find documentation about ChartsDefaultTheme

Unfortunately, there isn't documentation for that.

helha54 commented 3 years ago

Thanks again for the help