Ein Panel stellt an sich kein eigenes graphisches Element dar. Es dient vielmehr dazu andrere Elemente aufzunehmen. Ein Panel ist also eine Art Behälter, in dem weitere graphische Elemente positioniert werden können. Somit ähnelt der Panel dem Frame, unterscheidet sich jedoch deutlich von diesem, da er keine Menubar aufnehmen kann, und immer ein Parent Object besitzen muß.
Mit Hilfe eines Panels lassen sich die Probleme des Beispiel aus Kapitel 2.5 beheben. In diesem Beispiel wurde ein Label animiert in einem Frame hin und her bewegt. Dabei tauchte das Label allerdings hinter die Menubar, und war in dieser Zeit nicht sichtbar. Weiterhin mußte permanent die Größe des Frames abgefragt werden, was zu deutlichen Laufzeitverzögerungen führte. Dies kann mit einem Panel vermieden werden, da ein Panel bei einer Größenveränderung einen Event an die Applikation meldet.
Im folgenden nun das optimierte Program:
/* Example panel.c */ : if(j_start()<0) printf("can't connect to server\n"),exit(0); frame = j_frame("better moving label"); menubar = j_menubar(frame); file = j_menu(menubar,"File"); doit = j_menuitem(file,"Start"); quit = j_menuitem(file,"Quit"); j_borderlayout(frame); panel = j_panel(frame); j_show(frame); label=j_label(panel,"400:300"); j_setpos(label,120,120); while(1) { if(run) obj=j_getaction(); else obj=j_nextaction(); if(obj==doit) { if(!run) { run=1; j_settext(doit,"Stop"); } else { run=0; j_settext(doit,"Start"); } } if(obj==panel) { p_width=j_getwidth(panel); p_height=j_getheight(panel); sprintf(str,"%d:%d",p_width,p_height); j_settext(label,str); l_width = j_getwidth(label); l_height = j_getheight(label); x=(p_width-l_width)/2; y=(p_height-l_height)/2; j_setpos(label,x,y); } if(run) { if((x+l_width >= p_width) || (x<1)) dx = -dx; if((y+l_height >= p_height) || (y<1)) dy = -dy; x+=dx; y+=dy; j_setpos(label,x,y); j_sync(); j_sleep(1000); } if((obj==quit) || (obj == frame)) break; } :
Da große Teile des Programms unverändert übernommen wurden soll hier nur der relevante Teil besprochen werden. Neu sind die Zeilen:
j_borderlayout(frame); panel = j_panel(frame);
In einem Objekt, das andere graphische Elemente aufnimmt (Frame, und wie wir jetzt auch wissen, ein Panel) kann neben einer fixen Positionierung auch eine automatische Positionierung vorgenommen werden. Dazu müssen sogenannte Layoutmanager an die Objekte gebunden werden. Genaueres findet man dazu im Kapitel 3. Im Beispiel weist der Borderlayout - Manager nun dem Panel den gesammten Platz zu, der in dem Frame vorhanden ist. Wird nun vom Benutzer die Größe des Frames verändert, so verändert sich auch die Größe des Panels. Damit wird automatisch ein Event des Panels ausgelöst:
if(obj==panel) { p_width=j_getwidth(panel); p_height=j_getheight(panel); sprintf(str,"%d:%d",p_width,p_height); j_settext(label,str); l_width = j_getwidth(label); l_height = j_getheight(label); x=(p_width-l_width)/2; y=(p_height-l_height)/2; j_setpos(label,x,y); }
Dieser Teil nimmt die wesentlichen Änderungen des Programms ein. Zunächst wird die geänderte Größe des Panels ermittelt und als String in den Label eingetragen. Die restlichen Zeilen ermitteln die neue Größe des Labels und positionieren dieses mittig im Panel.
Wichtig ist, daß dem Panel nur der freie Platz unterhalb der Menubar zugewiesen wird, sofern eine Menubar vorhanden ist. Daher kann das Label auch nicht mehr hinter der Menübar verschwinden. Der Einsatz der Prozedur j_sync() und j_sleep() wird hier wieder nötig, da das Programm nun so schnell läuft, daß das Label sonst nur wild umher zu springen scheint.