Can I add buttons on a TGraph?

It is fatal error and ROOT just able to recover.
Most probably - gPad value is not correct.
Try to restore this value at the end of EventDisplay::HighlightGraph() method

What exactly do you mean “restore”? Sorry I’m very bad at coding :frowning:

At the begin:

auto store = gPad;

and at the end:

gPad = store;

Thank you again and it solved the problem…Just try to understand what was wrong, I attach my slot function here, can you please have a look and tell me what caused that seg fault?

//at first time c_waveform will be a nullptr that because I want it appear after highlight is called
void EventDisplay::HighlightGraph(TVirtualPad* pad, TObject* obj, Int_t ihp, Int_t y){
        auto store = gPad;
        c_waveform = (TCanvas*)gROOT->GetListOfCanvases()->FindObject("c_waveform");
        std::cout<<"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<<std::endl;
        if(!c_waveform){
                std::cout<<"Make new Canvas for ADC waveform"<<std::endl;
                c_waveform = new TCanvas("c_waveform", "ADC waveform", 505, 0, 600, 400);
        }

        if(ihp == -1){
                delete c_waveform;
                return;
        }

        if(waveforms.size() != 0 && waveforms.find(ihp) != waveforms.end()){
                c_waveform->cd();
                waveforms.at(ihp)->Draw("APL");
                std::cout<<"Drawn graph"<<std::endl;
                gPad->Update();
        }
        gPad = store;
}

After you create new canvas - moving cursor over old canvas may not work. While gPad is set to new canvas.

Ah, assume I have a TCanvas* c which generate the signal, you mean after the gPad->Update(), gPad is setting to the c_waveform but the Canvas that generate signal is a different Canvas which is c, so in order to set the gPad back to the c I need to store gPad at the beginning and set back at the end? Is my understanding correct?

Generally you are correct.

But be careful - working with many canvas at a time is complicated.
And sometimes makes such problems.

Thank you!

Let me summarize this in case of someone else also face the same problem.
I made a simple example to show how to use user class member function as the slot function to receive the signal.
EventDisplay.cxx:

#include "EventDisplay.hxx"

EventDisplay::EventDisplay(){
        c1 = new TCanvas();
        c1->Connect("Highlighted(TVirtualPad*, TObject*, Int_t, Int_t)", "EventDisplay", this, "HighlightGraph(TVirtualPad*, TObject*, Int_t, Int_t)");
        x = {1,2,3,4,5};
        y = {1,2,3,4,5};

        g = new TGraph(x.size(), x.data(), y.data());
        c1->cd();
        g->SetMarkerStyle(58);
        g->SetMarkerColor(kRed);
        g->Draw("AP");
        g->SetHighlight();
        c1->Update();
        gSystem->ProcessEvents();
}

void EventDisplay::HighlightGraph(TVirtualPad* pad, TObject* obj, Int_t ihp, Int_t y){
        auto store = gPad; //store the current gPad pointer
        c_show = (TCanvas*)gROOT->GetListOfCanvases()->FindObject("c_show");
        if(!c_show){
                std::cout<<"showed new canvas"<<std::endl;
                c_show = new TCanvas("c_show", "Canvas that shows later", 505, 0, 600, 400);
                g_show = new TGraph();
        }

        if(ihp == -1){
                delete c_show;
                return;
        }

        c_show->cd();
        for(int i=0; i<50; i++){
                double t = (double)ihp + 1;
                if(i == 0) g_show->SetPoint(0, 0, 1);
                else g_show->SetPoint(i, i, sin(i/t) / (i/t));
        }
        g_show->SetMarkerStyle(20);
        g_show->SetMarkerColor(kBlue);
        g_show->Draw("APL");
        gPad->Update();
        gPad = store;
}

EventDisplay.hxx:

#ifndef _EVENTDISPLAY_HXX_
#define _EVENTDISPLAY_HXX_

#include <iostream>
#include <vector>
#include <TROOT.h>
#include <TSystem.h>
#include <TCanvas.h>
#include <TGraph.h>

class EventDisplay{
public:
        EventDisplay();
        void HighlightGraph(TVirtualPad* pad, TObject* obj, Int_t ihp, Int_t y); //this needs to be public!

private:
        TCanvas* c1;
        TCanvas* c_show;
        TGraph* g;
        TGraph* g_show;

        std::vector<double> x;
        std::vector<double> y;
};
#endif

main.cxx:

#include <TApplication.h>
#include "EventDisplay.hxx"

int main(int argc, char** argv){
        TApplication app("app", &argc, argv);
        EventDisplay eventDisplay;
        app.Run();
        return 0;
}

LinkDef.h:

#ifdef __CLING__
#pragma link C++ class EventDisplay;
#endif

Procedure how to make it run:
If one uses command line to compile:

  1. rootcling -f Dict.cxx EventDisplay.hxx LinkDef.h to generate the dictionary file Dict.cxx
`root-config --cxx --cflags --libs` -lgui main.cxx Dict.cxx EventDisplay.cxx -o main
  1. ./main

If one uses CMakeLists.txt, you should add this line:

ROOT_GENERATE_DICTIONARY(Dict EventDisplay.hxx LINKDEF LinkDef.h)

Here CMakeLists.txt file which compiles your project:

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

project(EventDisplay)

find_package(ROOT REQUIRED)
include(${ROOT_USE_FILE})

set(sources EventDisplay.cxx)
set(headers EventDisplay.hxx)

ROOT_GENERATE_DICTIONARY(G__EventDisplay ${headers} LINKDEF LinkDef.h)

#---Create a shared library with geneated dictionary

add_library(EventDisplay SHARED ${sources} G__EventDisplay.cxx)

target_include_directories(EventDisplay PRIVATE ${CMAKE_SOURCE_DIR})

#---Create  a main program using the library
add_executable(testgui main.cxx)
target_link_libraries(testgui EventDisplay ROOT::Gui)

But for me everything looks fine.
And code also works with new web-based graphics.
You can try it running:

./testgui --web