大画面液晶を使用中に ROOT でたくさん TCanvas を作った際に、重ならないように自動で綺麗に並べたいとき。
ちょっと整理していないコードだけど、とりあえずこれで動く。
void TileCanvases() { auto canvases = gROOT->GetListOfCanvases(); int x0 = 0; int y0 = 1000000000; int margin1 = 0; int margin2 = 0; // First get the menu bar position for(int i = 0; i < canvases->GetEntries(); i++) { auto can = (TCanvas*)canvases->At(i); if (i == 0) { margin2 = (can->GetWindowWidth() - can->GetWw())/2; margin1 = can->GetWindowHeight() - can->GetWh() - margin2; } if (y0 > can->GetWindowTopY()) { y0 = can->GetWindowTopY(); } } int w_display = gClient->GetDisplayWidth(); int h_display = gClient->GetDisplayHeight(); int x1 = x0; int y1 = y0; int ymax = 0; for(int i = 0; i < canvases->GetEntries(); i++) { auto can = (TCanvas*)canvases->At(i); int w_can = can->GetWindowWidth(); int h_can = can->GetWindowHeight(); if (x1 + w_can > w_display) { x1 = x0; // reset the xy position to the leftmost y1 = ymax + margin1; } if (y1 + h_can > h_display) { x1 = x0 + y0 ; // reset the x position to top left y1 = y0 * 2; } can->SetWindowPosition(x1 - margin2, y1 - margin1); x1 += w_can; if (ymax < y1 + h_can) { ymax = y1 + h_can; } } }
例えば次のようにすると、何をしているか分かるはず。
for(int i = 0; i < 10; i++) { int w = gRandom->Uniform(400, 600); int h = gRandom->Uniform(400, 600); auto can = new TCanvas(Form("can%d", i), Form("can%d", i), w, h); } TileCanvases();