Interactive TApplication

Hi rooters,

I am trying to make a simple executable that displays a canvas with a certain plot (in interactive mode, so that the user zoom in/out and do other things), and then asks the user whether or not to save a file.

I know I can open the canvas and “stop” the executable from exiting with TApplication, but how can I do input/output (even the simplest cin) while the application is running?

here’s a sample of my code:

int main(int argv, char** argc){

    /*
     Here I create and fill a TH2F "h"
    */

    TApplication* app = new TApplication("app",0,0);
    // Draw and save TH2F
    TCanvas* c = new TCanvas("c","c",800,600);
    TRootCanvas* rc = (TRootCanvas*)c->GetCanvasImp();
    h->Draw("colz");

    app->Run();

    // Ask user if they want to save 2d binning file
    std::cout<<"Do you want to save the 2d binning file? (y/n)\n";
    std::string answer;
    std::cin>>answer;
    if(answer=="y"){
        //Saving binning file...
    }

    return 0;
}

I would like the part “ask the user if they want to save the binning file” to be within the TApplication.

Another solution I thought of would be to use Connect and terminate the Application when the canvas is closed, addingrc->Connect("CloseWindow()", "TApplication", gApplication, "Terminate()"); after app->Run(), but this closes my executable entirely, and does not go to the following code where I ask the input to the user.

Any suggestions?

_ROOT Version: 6.26
_Platform: mac
_Compiler:c++14


You can try something like this:

int main(int argv, char** argc)
{
    /*
     Here I create and fill a TH2F "h"
    */
    TApplication* app = new TApplication("app",0,0);
    // Draw and save TH2F
    TCanvas* c = new TCanvas("c","c",800,600);
    TRootCanvas* rc = (TRootCanvas*)c->GetCanvasImp();
    h->Draw("colz");
    // Ask user if they want to save 2d binning file
    Int_t retval;
    new TGMsgBox(gClient->GetRoot(), gClient->GetRoot(),
                 "Question", "Do you want to save the 2d binning file?",
                 kMBIconQuestion, kMBYes | kMBNo | kMBCancel, &retval);
    if (retval == kMBYes)
       std::cout << "Saving binning file..." << std::endl;
    app->Run();
    return 0;
}

unfortunately I have a problem while linking this.
I get the following error message in my compiler/linker:

Undefined symbols for architecture arm64:
  "TGClient::Instance()", referenced from:
      _main in FitterBinningBuilder-ffe4ce.o
  "TGMsgBox::TGMsgBox(TGWindow const*, TGWindow const*, char const*, char const*, EMsgBoxIcon, int, int*, unsigned int, int)", referenced from:
      _main in FitterBinningBuilder-ffe4ce.o
  "TGClient::GetRoot() const", referenced from:
      _main in FitterBinningBuilder-ffe4ce.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [FitterBinningBuilder] Error 1

I included both:

#include "TGMsgBox.h"
#include "TGClient.h"

Make you can help with that?

You must link with libGui

Ok, now the compilation works but:

THis solution is ot ideal for me as:

  1. the Root canvas is not shown anymore, only the message box
  2. I would like it to work with a terminal I/O rather than a message box

Is it possible?

Weird, it works fine on Windows…

This is blocking the event loo. There might be other solutions, but it is maybe a conceptual issue. I’ll check tomorrow

    // Ask user if they want to save 2d binning file
    std::cout<<"Do you want to save the 2d binning file? (y/n)\n";
    std::string answer;
    while (1) {
       if (_kbhit()) {
          std::cin>>answer;
          if(answer=="y"){
              std::cout << "Saving binning file..." << std::endl;
              //Saving binning file...
          }
       }
       gSystem->ProcessEvents();
       gSystem->Sleep(20);
    }

I found a workaround:


    while(!returned){
        c->Update();
        gSystem->ProcessEvents();
        std::string answer = "";
        std::cout<<"\rDo you want to save the 2d binning file? (y/n)";
        std::cin>>answer;
        if (answer=="y" || answer=="Y" || answer=="yes" || answer=="Yes" || answer=="YES") {
            returned=true;
           // Saving binning file
            theApp.Terminate();
        }else{
            returned=true;
            std::cout<<"Binning file not saved.\n";
            theApp.Terminate();
        }
    }

it is a bit ugly, and it works only partially: the only annoying thing is that I lose the interactivity of the canvas (zooming in/out)…

As I said, std::cin>>answer; is blocking the event loop. But up to you if you want to keep the input from the console…

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.