Wiesław Kurko

Wiesław Kurko Student,
Politechnika
Rzeszowska im.
Ignacego
Łukasiewicza

Temat: SwingWorker. Problem z zastosowaniem

Witam,

Mam problem z wykorzystaniem SwingWorker. Chcę w oddzielnych plikach stworzyć klasę, która wykonuje czasochłonne obliczenia i interfejs graficzny, który te wyświetla postęp tych obliczeń. Klasa licząca i interfejs graficzny znajdują się w osobnych paczkach. Z tego co czytałem to jest to tworzone w jednym pliku za pomocą klas wewnętrznych. Jest jakiś sposób na rozdzielenie tych klas? Chodzi mi o to aby program liczący co jakiś czas (np. co jedną minutę) wyrzucał wynik, który ma służyć do rysowania wykresu. Co prawda mogę to zrobić w inny sposób, ale wolałbym za pomocą SwingWorker. Chciałbym to zrobić w miarę elegancki sposób. Program działa na liczbach.
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: SwingWorker. Problem z zastosowaniem

Sprawdzałeś dokumentację javax.swing.SwingWorker? Tam jest to ładnie opisane.
Jeśli stworzysz klasę dziedziczącą po SwingWorkerze, która w doInBackground() będzie wykonywała te czasochłonne obliczenia, to musisz jedynie zadbać aby co pewien czas wywoływać w niej publish(). Jeśli nie chcesz z niej bezpośrednio manipulować interfejsem graficznym, to możesz nadpisać process() tak aby ustawiał wyniki uzyskane do danej chwili w jakimś property i odpalał firePropertyChange(), aby poinformować, że są jakieś nowe dane.
Tym bardziej, że i tak warto zrobić listener'a, który będzie nasłuchiwał PropertyChangeEvent i dodać go do SwingWorkera, aby wiedzieć kiedy SwingWorker zakończy działanie (property state będzie miało wartość SwingWorker.StateValue.DONE). Wtedy przez get() można po pierwsze pobrać wartość wynikową (o ile taka jest), a co chyba ważniejsze get() zwróci nam wyjątek jeśli w czasie działania SwingWrokera jakiś się zdarzył.
Wiesław Kurko

Wiesław Kurko Student,
Politechnika
Rzeszowska im.
Ignacego
Łukasiewicza

Temat: SwingWorker. Problem z zastosowaniem

Dzięki na odpowiedź. Trochę się rozjaśniło, ale jestem na poziomie podstawowym i sprawia mi to problem. Z powodu braku czasu chyba zrobię to za pomocą dodatkowego obiektu ze statycznymi polami, za pomocą których będą się mogły komunikować obie klasy. Widzę, że będę potrzebował więcej czasu zrozumienie wielowątkowości.

Jakby ktoś to potrafił wytłumaczyć na prostym przykładzie to byłbym wdzięczny. Myślę, że jeszcze komuś by się to przydało.
Przykład może składać się z trzech klas:
- klasa generująca całkowite liczby losowe z konkretnego przedziału np. od 0 do 100 i zlicza ilość trafień danej liczby;
- klasa znajdująca się w innej paczce tworzy co pewien czas histogram tych wylosowanych liczb;
- trzecia klasa służy do komunikacji między tymi klasami i ewentualnemu sterowaniu przebiegiem klasy generującej liczby losowe (zatrzymuje, wznawia działanie).
Klasa pierwsza i druga są oddzielnie od siebie.

Pozdrawiam
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: SwingWorker. Problem z zastosowaniem

Wiesław Kurko:
Przykład może składać się z trzech klas:
- klasa generująca całkowite liczby losowe z konkretnego przedziału np. od 0 do 100 i zlicza ilość trafień danej liczby;
- klasa znajdująca się w innej paczce tworzy co pewien czas histogram tych wylosowanych liczb;
- trzecia klasa służy do komunikacji między tymi klasami i ewentualnemu sterowaniu przebiegiem klasy generującej liczby losowe (zatrzymuje, wznawia działanie).
Klasa pierwsza i druga są oddzielnie od siebie.
Prawdę mówiąc brzmi to jak kawałek jakiegoś zadania na zaliczenie. A może by tak samemu spróbować?
We wspomnianej już dokumentacji javax.swing.SwingWorker jest link do tutoriala, w którym jest przykład czegoś bardzo podobnego. Symulacja rzutu monetą, która co jakiś czas pokazuje aktualne wyniki. Jest nawet kod źródłowy.

Pozdrawiam
Wiesław Kurko

Wiesław Kurko Student,
Politechnika
Rzeszowska im.
Ignacego
Łukasiewicza

Temat: SwingWorker. Problem z zastosowaniem

Kod źródłowy tej symulacji jest prosty, jest mi znany podobny przykład. Tak, jest to praca ale nie na zaliczenie. To co opisałem, to jest tylko prosty przykład, przedstawiający mój program. Mam dość dużą paczkę wykonującą czasochłonne obliczenia (duża sieci neuronowe) i chciałem sterować siecią, wyświetlać różnego typu wyniki w kilku oknach itd. W najgorszym razie zostanie tak jak jest, też działa. Aby skorzystać z tego przykładu muszę trochę zmodyfikować klasy. Program mógłby z powodzeniem działać w konsoli i nie byłoby problemów, ale to nie te czasy.

Dzięki za pomoc.

Pozdrawiam
Sebastian Kolski

Sebastian Kolski programista/DBA

Temat: SwingWorker. Problem z zastosowaniem

Wiesław Kurko:
- klasa generująca całkowite liczby losowe z konkretnego przedziału np. od 0 do 100 i zlicza ilość trafień danej liczby;


public class Worker extends SwingWorker<Long[], Void> {
private boolean finish = false;
private boolean pause = false;
private final Long[] result = new Long[100];

public Worker() {
super();
for (int i = 0; i < 100; i++) {
result[i] = 0L;
}
}

@Override
protected Long[] doInBackground() throws Exception {
Random random = new Random();

while (!finish) {
if (pause == true) {
synchronized(this) {
this.wait();
pause = false;
}
}

int i = random.nextInt(100);
synchronized(result) {
result[i]++;
}
publish();
// spowalniacz
Thread.sleep(100);
}

return result;
}

public void setFinish(boolean finish) {
this.finish = finish;
}

public void setPause(boolean pause) {
this.pause = pause;
}

public boolean isPause() {
return pause;
}

@Override
protected void process(List<Void> chunks) {
super.process(chunks);
// synchronizacja na tablicy (tu i w doInBackground) nie jest potrzebna,
// jeśli nie przeszkadza nam, że wyniki cząstkowe mogą być rozjechane
synchronized(result) {
firePropertyChange("results", null, Arrays.copyOf(result, result.length));
}
}}

- klasa znajdująca się w innej paczce tworzy co pewien czas histogram tych wylosowanych liczb;

Dowolna klasa która ma np metodę setData(Long[] data) w której na podstawie dostarczonych danych rysuje histogram.
- trzecia klasa służy do komunikacji między tymi klasami i ewentualnemu sterowaniu przebiegiem klasy generującej liczby losowe (zatrzymuje, wznawia działanie).

To może być jakieś okienko np z 3 przyciskami. Klasa implementuje PropertyChangeListener i ma referencję do klasy rysującej histogram (może to być ta sama klasa).
Procedury podpięte pod przyciski:

private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {
worker = new Worker();
worker.addPropertyChangeListener(this);
worker.execute();
}

private void pauseButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (worker.isPause() == true) {
synchronized(worker) {
worker.notifyAll();
}
} else {
worker.setPause(true);
}
}

private void finishButtonActionPerformed(java.awt.event.ActionEvent evt) {
worker.setFinish(true);
}


obsługa property change


public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName()) && evt.getNewValue().equals(StateValue.DONE)) {
try {
Long[] result = worker.get();
rysowacz.setData(result);
} catch (ExecutionException ex) {
// obsługa błędów
} catch (InterruptedException ex) {
// obsługa błędów
}
} else if ("results".equals(evt.getPropertyName())) {
rysowacz.setData((Long[]) evt.getNewValue());
}
}

Klasa pierwsza i druga są oddzielnie od siebie.

Pozdrawiam

Następna dyskusja:

Problem z Web Service




Wyślij zaproszenie do