Search code examples
c++plotmemory-leakswxwidgetswxmathplot

wxMathPlot plot freezes the system on resize


I have a plot created using wxMathplot library, at initial lunch the plot works perfect, but when I resize the window it stucks and the laptop freezes until I restart it, before the freeze, I noticed a linear increase in consuming RAM till saturation, sort of memory leak, when I comment out the mpWindow and its related components, everything works normal, here is a portion of my code

#include <wx/wx.h>
#include "wxmathplot/mathplot.h"

class PlotUI : public wxPanel
{
public:
    PlotUI(wxWindow* parent, int ID);

    void setTopPlot();
    void setBottomLeftPlot();
    void setBottomRightPlot();
    void OnRefreshTopPlot(wxCommandEvent& evt);
    void OnSaveTopPlot(wxCommandEvent& evt);
    void OnRefreshBottomLeftPlot(wxCommandEvent& evt);
    void OnSaveBottomLeftPlot(wxCommandEvent& evt);
    void OnRefreshBottomRightPlot(wxCommandEvent& evt);
    void OnSaveBottomRightPlot(wxCommandEvent& evt);

public:
    wxBoxSizer* mainSizer;
    wxBoxSizer* topSizer;
    wxBoxSizer* bottomSizer;
    wxStaticBox* topPlot;

    wxBoxSizer* topPlotSizer;
    wxBoxSizer* topPlotSizer_plot;
    wxBoxSizer* topPlotSizer_control;
    wxStaticBox* topPlotSB_control;
    wxStaticBox* topPlotSB_plot;
    wxCheckBox* T_1_checkBox;
    wxCheckBox* T_2_checkBox;
    wxCheckBox* T_3_checkBox;
    wxButton* refreshTopPlot;
    wxButton* saveTopPlot;
    mpWindow* topPlot_plot;


};

PlotUI::PlotUI(wxWindow* parent, int ID) : wxPanel(parent, ID)
{
    SetBackgroundColour(ztcColorCred);
    mainSizer = new wxBoxSizer(wxVERTICAL);
    topSizer = new wxBoxSizer(wxHORIZONTAL);
    bottomSizer = new wxBoxSizer(wxHORIZONTAL);

    topPlot = new wxStaticBox(this, -1,"");
    setTopPlot();
    topSizer->Add(topPlot, 1, wx1AND | wxALL, 5);

    mainSizer->Add(topSizer, 1, wx1AND);

    SetSizer(mainSizer);
}

void PlotUI::setTopPlot()
{
   topPlotSizer = new wxBoxSizer(wxHORIZONTAL);
   topPlotSizer_control = new wxBoxSizer(wxVERTICAL);
   topPlotSizer_plot = new wxBoxSizer(wxVERTICAL);

   topPlotSB_control = new wxStaticBox(topPlot, -1, "",wxDefaultPosition,wxSize(100,-1));

   topPlotSizer_control->AddStretchSpacer(1);

   T_1_checkBox = new wxCheckBox(topPlotSB_control, -1,"T_1");
   topPlotSizer_control->Add(T_1_checkBox, 0, wx1AND | wxALL, 10);

   T_2_checkBox_checkBox = new wxCheckBox(topPlotSB_control, -1, "T_2");
   topPlotSizer_control->Add(T_2_checkBox_checkBox, 0, wx1AND | wxALL, 10);

   T_s_checkBox = new wxCheckBox(topPlotSB_control, -1, "T_3");
   topPlotSizer_control->Add(T_s_checkBox, 0, wx1AND | wxALL, 10);

   refreshTopPlot = new wxButton(topPlotSB_control,-1,"Refresh");
   refreshTopPlot->Bind(wxEVT_BUTTON, &PlotUI::OnRefreshTopPlot,this);
   topPlotSizer_control->Add(refreshTopPlot, 0, wx1AND | wxALL, 10);

   saveTopPlot = new wxButton(topPlotSB_control, -1, "Save");
   saveTopPlot->Bind(wxEVT_BUTTON, &PlotUI::OnSaveTopPlot,this);
   topPlotSizer_control->Add(saveTopPlot, 0, wx1AND | wxALL, 10);

   topPlotSizer_control->AddStretchSpacer(1);

   topPlotSB_control->SetSizer(topPlotSizer_control);

   topPlotSizer->Add(topPlotSB_control, 0, wx1AND | wxALL, 10);

   topPlotSB_plot = new wxStaticBox(topPlot, -1, "");
   topPlot_plot = new mpWindow(topPlotSB_plot, -1);
   topPlotSizer_plot->Add(topPlot_plot, 1, wx1AND);
   topPlotSB_plot->SetSizer(topPlotSizer_plot);
   topPlotSizer->Add(topPlotSB_plot, 1, wx1AND | wxALL, 10);

   topPlot->SetSizer(topPlotSizer);
}

void PlotUI::OnRefreshTopPlot(wxCommandEvent& evt)
{
    AppData& appData = AppData::getInstance();
    std::vector<double>& x = userData.xData;
    std::vector<double>& T_1 = userData.yData;
    std::vector<double>& T_2_checkBox = userData.fitTdata;
    std::vector<double>& T_3 = userData.fitTSdata;

    if (T_1_checkBox->IsChecked() && T_2_checkBox_checkBox->IsChecked() && T_3_checkBox->IsChecked())
    {
        wxMessageBox("top 111");
        if((topPlot_plot->CountAllLayers())>0) topPlot_plot->DelAllLayers(false, true);
        topPlot_plot->SetMargins(30, 30, 40, 60);
        topPlot_plot->SetBackgroundColour(ztcColorCred);
        mpScaleX* xAxis = new mpScaleX("Wavelength (nm)", mpALIGN_BOTTOM, false, mpX_NORMAL);
        mpScaleY* yAxis = new mpScaleY("Transmittance (AU)", mpALIGN_LEFT, false);
        xAxis->SetDrawOutsideMargins(false);
        yAxis->SetDrawOutsideMargins(false);
        topPlot_plot->AddLayer(xAxis);
        topPlot_plot->AddLayer(yAxis);
        mpFXYVector* T_1_Layer = new mpFXYVector("T_1");
        T_1_Layer->SetData(x, T_1);
        T_1_Layer->SetPen(wxPen(*wxRED, 3, wxPENSTYLE_SOLID));

        mpFXYVector* T_2_checkBox_Layer = new mpFXYVector("T_2");
        T_2_checkBox_Layer->SetData(x, T_2_checkBox);
        T_2_checkBox_Layer->SetPen(wxPen(*wxBLUE, 3, wxPENSTYLE_SOLID));

        mpFXYVector* T_s_Layer = new mpFXYVector("T_3");
        T_s_Layer->SetData(x, T_3);
        T_s_Layer->SetPen(wxPen(*wxGREEN, 3, wxPENSTYLE_SOLID));

        topPlot_plot->AddLayer(T_1_Layer);
        topPlot_plot->AddLayer(T_2_checkBox_Layer);
        topPlot_plot->AddLayer(T_s_Layer);
        topPlot_plot->Fit(0.0,5000.0,0.0,1.0);
        topPlot_plot->UpdateAll();
        topPlotSizer_plot->Layout();
    }
}

I used the library before without problem

I tried to put the plot in separate class, and to skip the resize event, I did some debugging in VS2022.


Solution

  • I noticed that the issue is comming from the event handling mechanism in wxwidgets in debug mode (this is what I think , I am not wxwidgets expert), I switched to release mode to test my idea and every thing worked perfectly with the same code. this solved the issue for me, I will not accept my answer as final to see if the experts of wxwidgest will suggest a better solution.