Is this The Correct Way to Pass std::vector<TCanvas*>?

Anything which isn’t clear - just ask!!

For a start I should add I’m using QT-ROOT but the object TQtWidget is just a back for TCanvas - so the SetupCanvas part doesn’t really matter but I included it for reference. I’m trying to separate my “Model” from my “View”. This means ideally I’d like my canvas to be created in the model, then I can pass this over to my view which will display it.

Also I’m using ROOT v5.3

Setting Up

Some useful variables:

std::vector<TQtWidget*> m_vectorCanvas; //just a back for TCanvas std::vector<QGroupBox*> m_vectorGroupBox; std::vector<QHBoxLayout*> m_vectorLayout;

[code] void DataTestTab::setupCanvas(int cNCbc)
{
for (int i=0; i<cNCbc; i++)
{
m_vectorCanvas.push_back(new TQtWidget(this));

        //m_vectorCanvas[i]->GetCanvas()->SetFillColor(i);
        QHBoxLayout *loH = new QHBoxLayout(this);

        loH->addWidget(m_vectorCanvas[i]);
        m_vectorLayout.push_back(loH);

        QGroupBox *gbCanvas = new QGroupBox(this);
        QString title = QString("CBC %1").arg(i);
        gbCanvas->setTitle(title);
        gbCanvas->setLayout(m_vectorLayout[i]);
        m_vectorGroupBox.push_back(gbCanvas);

        ui->loCbcBox->addWidget(m_vectorGroupBox[i]);
    }
}[/code]

This (Almost) Works

It draws the graphs (albeit in the wrong order):

[code] void DataTestTab::drawTest()
{
static Int_t HistoID = 1;
qDebug() << "in Testing env ";
std::vector<TH1D*> graphs;
std::vector<TCanvas*> vCanvas;

    TString name("h1_");
    Bool_t build = false;
    
    for (int i = 0; i <m_vectorCanvas.size() ; i++)
    {
        std::unique_ptr<TCanvas> uCanvas(new TCanvas(build));
        TCanvas *cCanvas = new TCanvas(build);
        name += HistoID++;

        vCanvas.push_back(cCanvas);
        vCanvas.at(i)->cd();


        TH1D *h1 = new TH1D(name.Data(),name.Data(),10,0, 10);
        graphs.push_back(h1);
        graphs.at(i)->Fill(i);

        //graphs.at(i)->Draw();
        graphs.at(i)->DrawCopy();

        m_vectorCanvas.at(i)->GetCanvas()->SetFillColor(i+5);
        m_vectorCanvas.at(i)->cd();

        qDebug() << i;

        m_vectorCanvas.at(i)->GetCanvas()->SetCanvas(vCanvas.at(i));
        m_vectorCanvas.at(i)->Refresh();
    }
}[/code]

Result:

The Method Which Doesn’t Work

I try and move this now to another class, I basically pass the vector of TCanvas pointers via the signal and slots mechanism. All you need to know is basically when you see “emit”, it forwards this onto my other class.

[code] void DataTestWorker::doWork()
{
static Int_t HistoID = 1;
qDebug() << "in Testing env ";
std::vector<TH1D*> graphs;
std::vector<TCanvas*> vCanvas;

    TString name("h1_");
    Bool_t build = false;

    for (int i = 0; i <2 ; i++)
    {
        TCanvas *cCanvas = new TCanvas(build);
        name += HistoID++;

        vCanvas.push_back(cCanvas);
        vCanvas.at(i)->cd();

        TH1D *h1 = new TH1D(name.Data(),name.Data(),10,0, 10);
        graphs.push_back(h1);
        graphs.at(i)->Fill(i);

        graphs.at(i)->Draw();

    }
    emit sendGraphData(vCanvas); //void sendGraphData(const std::vector<TCanvas*> &canvas); // This forwards on the vCanvas to the DrawGraph method in the below class....[/code]

[code] void DataTestTab::drawGraph(const std::vector<TCanvas*> &canvas)
{
for (int i=0; i<m_vectorCanvas.size(); i++)
{
canvas.at(i)->cd();
m_vectorCanvas.at(i)->cd();
m_vectorCanvas.at(i)->GetCanvas()->SetCanvas(canvas.at(i));
m_vectorCanvas.at(i)->Refresh();
//m_vectorCanvas.at(i)->GetCanvas()->Update();

    }
}[/code]

Output:

So…
Any ideas as to what is happening here? I have a feeling I have funny memory management. Or is there a better way to be passing around this TCanvas?

I considered using std::vector<std::unique_ptr<TCanvas>> but when trying to use SetCanvas(), I get the following error:

error: no matcing function to call to 'TCanvas::SetCanvas(__gnu_cxx::__alloc_traits<std::allocator<std::unique_ptr<TCanvas> > >::value_type&)'