Wątki i płynne przejścia pomiędzy obrazkami

0

Witam, korzystając z SWT chciałem zrobić płynne przejście tła widgetu, gdy użytkownika najedzie na niego (mouseenter), a gdy użytkownik opuści element (mouseexit) powrót do braku tła. Tak wygląda mój kod:

public class Hover {
	Label lab;
	Listener mouseEnter = new Listener() {
		public void handleEvent(Event arg0) {
			for (int i=0;i<255;i++) {
				final int a=i;
				Display.getDefault().asyncExec(new Runnable() {
					public void run() {
						Image img = new Image(Display.getDefault(), 50, 50);
						GC gc = new GC(img);
						gc.setAlpha(a);
						gc.drawImage(SWTResourceManager.getImage(Hover.class,"/hover.png"), 0,0,50,50,0,0,50,50);
						gc.dispose();
						lab.setBackgroundImage(img);
					}
				});
				
			}
		}
	};
	Listener mouseExit = new Listener() {
		public void handleEvent(Event arg0) {
			lab.setBackgroundImage(null);
		}
	};
	
	public static void main(String[] args) {
		Hover h = new Hover();
		h.go();
	}
	
	public void go() {
		  Display display = new Display();
		    Shell shell = new Shell(display);
		    shell.setText("Test");
		    shell.setSize(300, 200);
			shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
		    shell.setBackground(SWTResourceManager.getColor(255, 255, 255));
		    
		    lab = new Label(shell,0);
		    lab.setBounds(10, 10, 50, 50);
		    lab.setText("Test");
		    lab.addListener(SWT.MouseEnter, mouseEnter);
		    lab.addListener(SWT.MouseExit, mouseExit);
		    shell.open();
		    
		    while (!shell.isDisposed()) {
		      if (!display.readAndDispatch())
		        display.sleep();
		    }
		    display.dispose();
	}

}

Problem w tym, że to wszystko nie działa tak jak powinno.
a) tekst miga podczas płynnego przejścia
b) gdy kursorem opuścimy widget zanim pętla dojdzie do końca - tło nie jest zmieniane na puste
c) gdy jest więcej widgetów akcje nie dzieją się równolegle, tylko najpierw pierwszy najechany element zmieni swoje tło, potem dopiero drugi, etc. widać to najlepiej w praktyce.

Można cos z tym zrobić? A może to ograniczenia SWT?

0

miganie obrazu - zastosuj podwójne buforowanie
nie używaj wątków, bo kolejka AWT i tak przecież ma swój wątek

0

Nieco inne podejście.

  1. Pętla w samej obsłudze zdarzeń - nawet jeżeli wywołuje coś asynchronicznie - nie jest dobrym rozwiązaniem. Z obsługi zdarzeń odpal sobie albo nowy wątek robiący w pętli te same wywołania, albo timera (na jedno wychodzi).
  2. Migotanie tekstu - zrób sobie dwie warstwy - przed animacją tekst wyrenderuj jeden raz na roboczą bitmapę i łącz ją na bieżąco z obrazkiem o zmiennym alpha. Tak na marginesie renderowanie tekstu jest w wielu systemach bardzo wolne (a on się przecież ma nie zmieniać). Migotanie, to nic innego jak odrysowywanie obrazka raz z właściwą zawartością, a raz bez niej. W tym drugim wypadku jest to zwykle skutek jakiegoś Twojego działania - często pośredniego - np. wymuszenie odrysowania kontrolki przez system.
  3. Nigdzie nie widzę, aby mouseExit powodowało przerwanie pętli generującej animację. Konieczność takiego przerwania powoduje, że nie powinno się to dziać w obsłudze innego (wcześniejszego zdarzenia). Pętla o której wspomniałem w p.1 powinna mieć w warunku możliwość przerwania jej z zewnątrz, a w przypadku timera powinien on zostać po prostu zatrzymany. Wrzucone raz lab.setBackgroundImage(null) niewiele daje skoro w innym miejscu wciąż spamujesz lab.setBackgroundImage(img).
  4. Polecenie new grzebiące po stercie w pętli animacji, to wyjątkowo zły pomysł, szczególnie w połączeniu z dispose(). Jest to wolne i zagrożone odpaleniem śmieciarki. Nie ma potrzeby usuwać narzędzia rysującego skoro wiesz, że za chwilę musisz go użyć. Likwiduj go po skończonej lub przerwanej animacji.
  5. Przypadek C bierze się właśnie ze złej obsługi animacji. Nie ma większego znaczenia czy to SWT, czy inne GUI. Każde asynchroniczne gui powoduje, że pojawia się konieczność okresowego "invalidowania" kontrolek podlegających animacji. I trzeba to robić środkami tego gui, a nie przez próby naginania jego wymagań do potrzeb.

1 użytkowników online, w tym zalogowanych: 0, gości: 1