Właśnie znalazłem bardziej eleganckie rozwiązanie. Co prawda nie jest ono docelowe bo używa prywatnych klas Suna obecnych w JRE, ale działa i w przyszłości będzie mogło być niezależne od tego co sobie Sun wymyśli. Wymagać to będzie podstawienia tylko jednego pliku class w nowszej wersji. A oto kod:
RejestratorZmianyGrafiki.java:
/**
* Rejestruje zmiany trybu graficznego
* Powiela sun.awt.DisplayChangedListener dla niewrażliwości
* od wpływu zmian przyszłych implementacji sun.awt.*
* @author Olamagato
* @version 1.0
*/
public interface RejestratorZmianyGrafiki
{
void zmienionoPaletę();
void zmienionoRozdzielczość();
}
RejestracjaZmianyGrafiki.java
import java.awt.GraphicsEnvironment;
/**
* Obsługuje rejestratora zdarzeń zmiany trybu graficznego
* Rejestruje i wyrejestrowuje wywołania
* @author Olamagato
*/
public class RejestracjaZmianyGrafiki
{
/**
* Ustawia warunki do informowania obserwatora o zmianach trybu
* graficznego
* @param obserwator klasa implementująca RejestratorZmianyGrafiki
*/
public RejestracjaZmianyGrafiki(RejestratorZmianyGrafiki obserwator)
{
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
if(ge instanceof sun.java2d.SunGraphicsEnvironment)
{
sge = (sun.java2d.SunGraphicsEnvironment)ge;
this.obserwator = obserwator;
}
}
/**
* Rejestruje obserwatora dla zmian trybu graficznego
* Nadmiarowe rejestracje są ignorowane.
*/
public synchronized void włącz()
{
if(obserwator == null) return;
if(!zarejestrowano)
{ //sge i powiadamiacz zawsze istnieje
sge.addDisplayChangedListener(powiadamiacz);
zarejestrowano = true;
}
}
/**
* Wyrejestrowuje obserwatora zmian trybu graficznego
* Nadmiarowe wyrejestrowania są ignorowane.
*/
public synchronized void wyłącz()
{
if(obserwator == null) return;
if(zarejestrowano)
{ //sge i powiadamiacz zawsze istnieje
sge.removeDisplayChangedListener(powiadamiacz);
zarejestrowano = false;
}
}
//Zachowuje stan środowiska gdyby cudem nie był już dostępny w czasie wyrejestrowywania
private sun.java2d.SunGraphicsEnvironment sge;
//odnośnik do klasy powiadamianej o zmianach
private RejestratorZmianyGrafiki obserwator;
//pozwala na wielokrotne rejestracje bez ryzyka wykrzaczenia
private boolean zarejestrowano;
private sun.awt.DisplayChangedListener powiadamiacz =
new sun.awt.DisplayChangedListener() //nikt się nie dobierze z zewnątrz
{
/** Wywoływana tylko przez sun.awt.DisplayChangedListener */
public void displayChanged() { obserwator.zmienionoRozdzielczość(); }
/** Wywoływana tylko przez sun.awt.DisplayChangedListener */
public void paletteChanged() { obserwator.zmienionoPaletę(); }
};
}
Całość wymagać będzie tylko stworzenia obiektu RejestracjaZmianyGrafiki i podaniu jej klasy, która będzie obserwować zmiany grafiki w momencie gdy się pojawią. Rozwiązanie po prostu podkleja się do tego co robi Swing ponieważ i ta biblioteka potrzebuje uaktualnić bufory ekranowe po zmianie rozdzielczości/kolorów.
Można tę klasę jeszcze zabezpieczyć jako tako przed nagłym zniknięciem pakietu sun.* na innych JVM niż Sunowskich, aby przynajmniej nie wysypywała reszty programu oraz ewentualnie dodać obsługę finalize dla przypadku gdy ktoś zapomni wyłączyć rejestrację, a klasa pójdzie do śmieci (pewnie tylko po to, żeby wyrzucić błąd).