Logo ROOT  
Reference Guide
No Matches
drag_and_drop.C File Reference

Detailed Description

This tutorial illustrates how to use drag and drop within ROOT.

Select a list tree item with a mouse press, drag it (move the mouse while keeping the mouse button pressed) and release the mouse button in any pad inside the canvas or in the top list tree item ("Base"). When the button is released, the selected data is "dropped" at that location, displaying the object in the canvas or adding (copying) it in the list tree.

#include "TROOT.h"
#include "TApplication.h"
#include "TSystem.h"
#include "TGFrame.h"
#include "TGButton.h"
#include "TGLabel.h"
#include "TGMenu.h"
#include "TGFileDialog.h"
#include "TBrowser.h"
#include "TCanvas.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TF2.h"
#include "TGraph.h"
#include "TImage.h"
#include "TRandom.h"
#include "TGMsgBox.h"
#include "TGPicture.h"
#include "TGListTree.h"
#include "TObjString.h"
#include "TMessage.h"
#include "TTimer.h"
#include "TGDNDManager.h"
#include <cmath>
const char gHelpDND[] = "\
Drag & Drop (DnD)\n\
Drag and Drop support is implemented on Linux via Xdnd, the\n\
drag and drop protocol for X window system, and on Windows\n\
via the Clipboard.\n\
Users can selects something in ROOT with a mouse press, drags\n\
it (moves the mouse while keeping the mouse button pressed) and\n\
releases the mouse button somewhere else. When the button is\n\
released the selected data is \"dropped\" at that location. This\n\
way, a histogram from an opened ROOT file in the browser can be\n\
dragged to any TCanvas. A script file from the browser can be\n\
dropped to a TGTextView or TGTextEdit widget in TGTextEditor.\n\
On Linux, it is possible to drag objects between ROOT and an\n\
external application. For example to drag a macro file from the\n\
ROOT browser to the Kate editor. On Windows, drag and drop works\n\
only within a single ROOT application, but it is possible to drag\n\
from the Windows Explorer to ROOT (e.g. a picture file to a canvas\n\
or a text file to a text editor).\n\
const char gReadyMsg[] = "Ready. You can drag list tree items to any \
pad in the canvas, or to the \"Base\" folder of the list tree itself...";
class DNDMainFrame : public TGMainFrame {
TRootEmbeddedCanvas *fEc; // embedded canvas
TGTextButton *fButtonExit; // "Exit" text button
TGMenuBar *fMenuBar; // main menu bar
TGPopupMenu *fMenuFile; // "File" popup menu entry
TGPopupMenu *fMenuHelp; // "Help" popup menu entry
TCanvas *fCanvas; // canvas
TGListTree *fListTree; // left list tree
TGListTreeItem *fBaseLTI; // base (root) list tree item
TGLabel *fStatus; // label used to display status
TGraph *fGraph; // TGraph object
TH1F *fHist1D; // 1D histogram
TH2F *fHist2D; // 2D histogram
DNDMainFrame(const TGWindow *p, int w, int h);
virtual ~DNDMainFrame();
void DoCloseWindow();
void HandleMenu(Int_t);
TObject *GetObject(const char *obj);
void DataDropped(TGListTreeItem* item, TDNDData* data);
void ResetStatus();
//ClassDef(DNDMainFrame, 0); // Mainframe for Drag and Drop demo
const char *dnd_types[] = {
"ROOT files", "*.root",
"ROOT macros", "*.C",
"All files", "*",
0, 0
static Atom_t gRootObj = kNone;
DNDMainFrame::DNDMainFrame(const TGWindow *p, int w, int h) :
TGMainFrame(p, w, h), fGraph(0), fHist1D(0), fHist2D(0)
// Constructor.
const TGPicture *pic = 0;
fMenuBar = new TGMenuBar(this, 35, 50, kHorizontalFrame);
fMenuFile = new TGPopupMenu(gClient->GetRoot());
fMenuFile->AddEntry(" &Open...\tCtrl+O", M_FILE_OPEN, 0,
fMenuFile->AddEntry(" &Browse...\tCtrl+B", M_FILE_BROWSE);
fMenuFile->AddEntry(" &New Canvas\tCtrl+N", M_FILE_NEWCANVAS);
fMenuFile->AddEntry(" &Close Window\tCtrl+W", M_FILE_CLOSEWIN);
fMenuFile->AddEntry(" E&xit\tCtrl+Q", M_FILE_EXIT, 0,
fMenuFile->Connect("Activated(Int_t)", "DNDMainFrame", this,
fMenuHelp = new TGPopupMenu(gClient->GetRoot());
fMenuHelp->AddEntry(" &About...", M_HELP_ABOUT, 0,
fMenuHelp->Connect("Activated(Int_t)", "DNDMainFrame", this,
fMenuBar->AddPopup("&File", fMenuFile, new TGLayoutHints(kLHintsTop|kLHintsLeft,
0, 4, 0, 0));
fMenuBar->AddPopup("&Help", fMenuHelp, new TGLayoutHints(kLHintsTop|kLHintsRight));
AddFrame(fMenuBar, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 2, 2, 5));
TGHorizontalFrame *hfrm = new TGHorizontalFrame(this, 10, 10);
TGCanvas *canvas = new TGCanvas(hfrm, 150, 100);
fListTree = new TGListTree(canvas, kHorizontalFrame);
fEc = new TRootEmbeddedCanvas("glec", hfrm, 550, 350);
hfrm->AddFrame(canvas, new TGLayoutHints(kLHintsLeft | kLHintsExpandY, 5, 5));
fCanvas = fEc->GetCanvas();
fCanvas->Divide(3, 2);
fBaseLTI = fListTree->AddItem(0, "Base");
TGHorizontalFrame *hf = new TGHorizontalFrame(this, 10, 10);
fStatus = new TGLabel(hf, new TGHotString(gReadyMsg));
10, 10, 10, 10));
fButtonExit = new TGTextButton(hf, " &Exit... ", 3);
fButtonExit->SetToolTipText("Exit Application (ROOT)");
fButtonExit->Connect("Clicked()" , "TApplication", gApplication,
10, 10, 10, 10));
AddFrame(hf, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
gRootObj = gVirtualX->InternAtom("application/root", kFALSE);
TGraph *gr = (TGraph *)GetObject("Graph");
pic = gClient->GetPicture("f1_t.xpm");
item = fListTree->AddItem(fBaseLTI, gr->GetName(), gr, pic, pic);
fListTree->SetToolTipItem(item, "Simple Graph");
TH1F *hpx = (TH1F *)GetObject("1D Hist");
pic = gClient->GetPicture("h1_t.xpm");
item = fListTree->AddItem(fBaseLTI, hpx->GetName(), hpx, pic, pic);
fListTree->SetToolTipItem(item, "1D Histogram");
TH2F *h2 = (TH2F *)GetObject("2D Hist");
pic = gClient->GetPicture("h2_t.xpm");
item = fListTree->AddItem(fBaseLTI, h2->GetName(), h2, pic, pic);
fListTree->SetToolTipItem(item, "2D Histogram");
TString rootsys(gSystem->UnixPathName(gSystem->Getenv("ROOTSYS")));
#ifdef G__WIN32
// remove the drive letter (e.g. "C:/") from $ROOTSYS, if any
if (rootsys[1] == ':' && rootsys[2] == '/')
rootsys.Remove(0, 3);
TString link = TString::Format("/%s/tutorials/image/rose512.jpg",
TImage *img = TImage::Open(link.Data());
if (img) {
// create a 16x16 icon from the original picture
img->Scale(16, 16);
pic = gClient->GetPicturePool()->GetPicture("rose512", img->GetPixmap(),
delete img;
else pic = gClient->GetPicture("psp_t.xpm");
TObjString *ostr = new TObjString(link.Data());
item = fListTree->AddItem(fBaseLTI, "Rose", ostr, pic, pic);
fListTree->SetToolTipItem(item, link.Data());
// open the base list tree item and allow to drop into it
// connect the DataDropped signal to be able to handle it
fListTree->Connect("DataDropped(TGListTreeItem*, TDNDData*)", "DNDMainFrame",
this, "DataDropped(TGListTreeItem*,TDNDData*)");
SetWindowName("ROOT DND Demo Application");
Connect("CloseWindow()", "DNDMainFrame", this, "DoCloseWindow()");
DontCallClose(); // to avoid double deletions.
// Destructor. Doesnt't do much here.
void DNDMainFrame::DoCloseWindow()
// Do some cleanup, disconnect signals and then really close the main window.
if (fGraph) { delete fGraph; fGraph = 0; }
if (fHist1D) { delete fHist1D; fHist1D = 0; }
if (fHist2D) { delete fHist2D; fHist2D = 0; }
fMenuFile->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
fMenuHelp->Disconnect("Activated(Int_t)", this, "HandleMenu(Int_t)");
fButtonExit->Disconnect("Clicked()" , this, "CloseWindow()");
fListTree->Disconnect("DataDropped(TGListTreeItem*, TDNDData*)", this,
delete fListTree;
void DNDMainFrame::DataDropped(TGListTreeItem *, TDNDData *data)
// Handle the drop event in the TGListTree. This will just create a new
// list tree item and copy the received data into it.
fStatus->ChangeText("I received data!!!");
if (data) {
const TGPicture *pic = 0;
TGListTreeItem *itm = 0;
char tmp[1000];
if (data->fDataType == gRootObj) {
TBufferFile buf(TBuffer::kRead, data->fDataLength, (void *)data->fData);
TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class());
sprintf(tmp, "Received DND data : Type = \"%s\"; Length = %d bytes;",
obj->ClassName(), data->fDataLength);
if (obj->InheritsFrom("TGraph"))
pic = gClient->GetPicture("f1_t.xpm");
else if (obj->InheritsFrom("TH2F"))
pic = gClient->GetPicture("h2_t.xpm");
else if (obj->InheritsFrom("TH1F"))
pic = gClient->GetPicture("h1_t.xpm");
itm = fListTree->AddItem(fBaseLTI, obj->GetName(), obj, pic, pic);
fListTree->SetToolTipItem(itm, obj->GetName());
else {
sprintf(tmp, "Received DND data: \"%s\"", (char *)data->fData);
TObjString *ostr = new TObjString((char *)data->fData);
TImage *img1 = TImage::Open("doc_t.xpm");
TImage *img2 = TImage::Open("slink_t.xpm");
if (img1 && img2) {
pic = gClient->GetPicturePool()->GetPicture("doc_lnk", img1->GetPixmap(),
delete img2;
delete img1;
else pic = gClient->GetPicture("doc_t.xpm");
itm = fListTree->AddItem(fBaseLTI, "Link...", ostr, pic, pic);
fListTree->SetToolTipItem(itm, (const char *)data->fData);
if (itm) itm->SetDNDSource(kTRUE);
TTimer::SingleShot(3000, "DNDMainFrame", this, "ResetStatus()");
TObject *DNDMainFrame::GetObject(const char *obj)
// Return the object specified in argument. If the object doesn't exist yet,
// it is firt created.
if (!strcmp(obj, "Graph")) {
if (fGraph == 0) {
const Int_t n = 20;
Double_t x[n], y[n];
for (Int_t i=0;i<n;i++) {
x[i] = i*0.1;
y[i] = 10*sin(x[i]+0.2);
fGraph = new TGraph(n, x, y);
return fGraph;
else if (!strcmp(obj, "1D Hist")) {
if (fHist1D == 0) {
fHist1D = new TH1F("1D Hist","This is the px distribution",100,-4,4);
Float_t px, py;
for ( Int_t i=0; i<10000; i++) {
gRandom->Rannor(px, py);
return fHist1D;
else if (!strcmp(obj, "2D Hist")) {
if (fHist2D == 0) {
Double_t params[] = {
130,-1.4,1.8,1.5,1, 150,2,0.5,-2,0.5, 3600,-2,0.7,-3,0.3
TF2 *f2 = new TF2("f2","xygaus + xygaus(5) + xylandau(10)",
-4, 4, -4, 4);
fHist2D = new TH2F("2D Hist","xygaus+xygaus(5)+xylandau(10)",
20, -4, 4, 20, -4, 4);
return fHist2D;
return 0;
void DNDMainFrame::HandleMenu(Int_t menu_id)
// Handle menu events.
static TString dir(".");
fi.fFileTypes = dnd_types;
switch (menu_id) {
// close the window and quit application
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
dir = fi.fIniDir;
// doesn't do much, but can be used to open a root file...
// start a root object browser
new TBrowser();
// open a root canvas
hd = new TRootHelpDialog(this, "About Drag and Drop...", 550, 250);
void DNDMainFrame::ResetStatus()
// Restore the original text of the status label and its original color.
void drag_and_drop()
// Main function (entry point)
DNDMainFrame *mainWindow = new DNDMainFrame(gClient->GetRoot(), 700, 400);
@ kHorizontalFrame
Definition GuiTypes.h:382
Handle_t Atom_t
WM token.
Definition GuiTypes.h:37
const Handle_t kNone
Definition GuiTypes.h:88
#define h(i)
Definition RSha256.hxx:106
int Int_t
Definition RtypesCore.h:45
const Bool_t kFALSE
Definition RtypesCore.h:92
double Double_t
Definition RtypesCore.h:59
float Float_t
Definition RtypesCore.h:57
const Bool_t kTRUE
Definition RtypesCore.h:91
R__EXTERN TApplication * gApplication
#define gClient
Definition TGClient.h:166
@ kFDOpen
@ kDeepCleanup
Definition TGFrame.h:50
@ kLHintsRight
Definition TGLayout.h:33
@ kLHintsExpandY
Definition TGLayout.h:38
@ kLHintsLeft
Definition TGLayout.h:31
@ kLHintsCenterY
Definition TGLayout.h:35
@ kLHintsTop
Definition TGLayout.h:34
@ kLHintsExpandX
Definition TGLayout.h:37
@ kTextLeft
Definition TGWidget.h:33
double sin(double)
#define gROOT
Definition TROOT.h:406
R__EXTERN TRandom * gRandom
Definition TRandom.h:62
@ kReadPermission
Definition TSystem.h:47
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
#define gVirtualX
Definition TVirtualX.h:338
virtual void Terminate(Int_t status=0)
Terminate the application by call TSystem::Exit() unless application has been told to return from Run...
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
@ kRead
Definition TBuffer.h:73
The Canvas class.
Definition TCanvas.h:23
Atom_t fDataType
Int_t fDataLength
void * fData
virtual void SetParameters(const Double_t *params)
Definition TF1.h:644
A 2-Dim function with parameters.
Definition TF2.h:29
virtual void AddFrame(TGFrame *f, TGLayoutHints *l=0)
Add frame to the composite frame using the specified layout hints.
Definition TGFrame.cxx:1102
const char ** fFileTypes
char * fIniDir
void SetIniDir(const char *inidir)
Set directory name.
void SetDNDSource(Bool_t onoff)
Definition TGListTree.h:123
Pixmap_t GetPicture() const
Definition TGPicture.h:65
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:575
2-D histogram with a float per channel (see TH1 documentation)}
Definition TH2.h:251
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Open(const char *file, EImageFileTypes type=kUnknown)
Open a specified image file.
Definition TImage.cxx:118
virtual void Scale(UInt_t, UInt_t)
Definition TImage.h:141
virtual void Merge(const TImage *, const char *="alphablend", Int_t=0, Int_t=0)
Definition TImage.h:172
virtual Pixmap_t GetPixmap()
Definition TImage.h:235
virtual Pixmap_t GetMask()
Definition TImage.h:236
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Collectable string class.
Definition TObjString.h:28
Mother of all ROOT objects.
Definition TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:359
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:130
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:445
virtual void Rannor(Float_t &a, Float_t &b)
Return 2 numbers distributed following a gaussian with mean=0 and sigma=1.
Definition TRandom.cxx:500
void SetText(const char *helpText)
Set help text from helpText buffer in TGTextView.
void Popup()
Show help dialog.
Basic string class.
Definition TString.h:136
const char * Data() const
Definition TString.h:369
TString & Prepend(const char *cs)
Definition TString.h:661
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2331
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1661
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1294
virtual const char * UnixPathName(const char *unixpathname)
Convert from a local pathname to a Unix pathname.
Definition TSystem.cxx:1061
static void SingleShot(Int_t milliSec, const char *receiver_class, void *receiver, const char *method)
This static function calls a slot after a given time interval.
Definition TTimer.cxx:256
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
TGraphErrors * gr
Definition legend1.C:25
Bertrand Bellenot

Definition in file drag_and_drop.C.