Thursday 28 October 2010

Heavyweight AWT bilesenleri ile Lightweight Swing Bilesenlerinin Beraber Kullanimi

Çoğu zaman kullandığımız Swing bileşenlerinin transparency(non-opaque) özelliğini kullanırız. Mesela kullandığımız JPanel veya JInternalFrame’e köşeleri oval olan bir border verip window manager’ın bize verdiği title barı kullanmak isteyemeyebiliriz, veya kendimize özgü uygulamada şeffaf olarak kullanılmasını istediğimiz bilgi panelleri olabilir. Uygulamamızda sadece Lightweight olan Swing bileşenlerini kullandığımızda bu durum sorun olmaz fakat yaptığımız uygulamayı heavyweight AWT bileşenleri üzerinde kullanmak istediğimiz zaman transparency sorun olacaktır. Çünkü heavyweight AWT bileşenleri transparent olamazlar. Bizim başımıza 3D GIS API’si WorldWind (http://worldwind.arc.nasa.gov/java/) kullanırken geldi. Uygulamamızı önce 2D GIS apilerini kullanarak geliştirdik. Sonrada uygulamaya 3D eklemeye karar verdik. Özelliği ekledimizde ana panel olarak GLCanvas sınıfından türeyen WorldWindowGLCanvas sınıfını kullanmıştık. Tabi alt tarafta AWT bir bileşen olunca uygulamadaki tüm transparancey özellik gitti, birde menülerde gezerken flickr problemi başladı. Aslında bunun çözümü çok basit GLCanvas yerine GLJPanel’den türeyen WorldWindowGLJPanel kullandığınız takdirde probleminiz çözülecektir.(WorldWind bizim yerimize düşünmüş).

Ama biz ilk başta bu sınıfı fark etmediğimizden dolayı başka bir takım çözümlere başvurmuştuk. Şimdi onları aktarayım. Öncelikle flickr probleminin çözümünü aktarayım. Uygulamanıza JVM paramatresi olarak -Dsun.awt.noerasebackground=true eklediğinizde bu kaybolacaktır. Gelelim ikinci sorunumuza Transparent panel. Bunun için Javanın sitesinde gerekli bilgiyi bulabilirsiniz ama yinede ben burada yaptığımız değişiklikleri aktarayım. Bu işi yaparken reflection kullanacağız ve AWTUtilitiesClass.setMixingCutoutShape() ile yapacağız. Bunun için aşağıdaki gibi bir sınıf oluşturuyoruz.



package X;
import java.awt.Component;
import java.awt.Shape;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AWTUtilitiesClass {
private static final Logger LOGGER = LoggerFactory.getLogger(AWTUtilitiesClass.class);
private static Method mSetComponentMixing;

static {
Class awtUtilitiesClass;
try {
awtUtilitiesClass = Class.forName("com.sun.awt.AWTUtilities");
mSetComponentMixing =
awtUtilitiesClass.getMethod("setComponentMixingCutoutShape", Component.class, Shape.class);
}
catch (Exception exc) {
LOGGER.error(exc.toString(), exc);
}
}

public static void setMixingCutoutShape(Component c, Shape s) {
if (mSetComponentMixing != null) {
try {
mSetComponentMixing.invoke(null, c, s);
}
catch (Exception exc) {
LOGGER.error(exc.toString(), exc);
}
}
}
}


Sonrada istediğimiz sınıfta setOpaque(false) dedikten sonra AWTUtilitiesClass.setMixingCutoutShape(this, new Rectangle());

çağırıyoruz. Burada bizim ekranlarımızın standart dışı (oval) olduğundan dolayı Rectangle yerinine kendimize özgü Polygon tanımlayarak verdik. Sizde istediğiniz gibi java.awt.Shape nesnesi kullanabilirsiniz.

http://java.sun.com/developer/technicalArticles/GUI/mixing_components/index.html

http://today.java.net/article/2009/11/02/transparent-panel-mixing-heavyweight-and-lightweight-components