Temat: JFrame, setVisible, nie do końca załadowane okno.
Dariusz Wawer:
Irek Słonina:
Tak wywołuje, próbowałem też np. w SwingWorkerze Runnable upakować. Nic to nie zmienia.
Same wątki nie blokują GUI. Blokuje czekanie na ich koniec, a to robię z wątku głównego, czyli tego samego z którego korzysta GUI.
Rozumiem. W takim razie nie czekaj na koniec, tylko zrób jakąś metodę, która wywoła setEnabled(false) na wszystkich elementach gui do wyłączenia, a gdy wątek się skończy, niech wywoła setEnabled(true).
Bo, jak rozumiem, wszystko sprowadza się do tego, by aplikacja nie pozwalała użytkownikowi na interakcję, gdy czeka na dane?
Wtedy problem by nie istniał. Problemem jest to, aby nie dopuścić
do działania drugiego pobrania rezultatu przed zakończeniem komunikacji
(czyli funkcja getRezultat() powinna mnie przytrzymać aż będę mógł z niej wyciągnąć coś sensownego).
Tak to chciałem zrobić żeby się nie urobić (wywołań Komunikat.wyslij() sa grube setki):
jButton_Akcja.addActionListener(new ActionListener() {
Komunikat k1 = new Komunikat();
k1.wyslij(obiekt);
int rezultatPierwszegoZapytania = k1.getRezultat();
InnyObiekt obiekt2 = new InnyObiekt();
obiekt2.setJakasWartosc(rezultatPierwszegoZapytania);
Komunikat k2 = new Komunikat();
k2.wyslij(obiekt2);
jLabel_Wynik.setText(k2.getRezultat());
});
public class Komunikat {
private boolean komunikatGotowy;
private int rezultat;
public void wyslij(Object zapytanie) {
komunikatGotowy = false;
pokazCosWGUISwiadczaceOPracyWTle(true);
new Thread(new Runnable() {
jakasMetodaRealizujacaKomunikacjeZSerwerem();
komunikatGotwy = true;
}).start();
}
public int getRezultat() {
while (!komunikatGotowy) {
System.out.println("czekam chwile");
try {
Thread.sleep(300);
} catch (ExceptionInterruptedCostam ex) {
ex.printStackTrace();
}
}
return rezultat;
}
pokazCosWGUISwiadczaceOPracyWTle(boolean trufals) {
// tutaj cuda jak setEnabled, new JFrame albo start/stop
// progressbara.
}
}
Kod pisany z palca, jedynie pokazujący metodologię.
Zamiast Thread.sleep(300) powinien być oczywiście np. join().
Kod w ActionListenerze bezpośrednio też jest brzydkim rozwiązaniem. Nie jest to jednak przedmiotem dyskusji.
Wnioski:
Generalnie doszedłem do tego, że jest to niewykonalne ponieważ Thread.sleep() / join() blokuje jedyny wątek, w którym może działać GUI.
Innej metody niż poniższe rozwiązanie nie widzę, choć bardzo nad tym boleję:
jButton_Akcja.addActionListener(new ActionListener() {
new Thread(new Runnable() {
Komunikat.pokazCosWGUISwiadczaceOPracyWTle(true);
Komunikat k1 = new Komunikat();
k1.wyslij(obiekt);
int rezultatPierwszegoZapytania = k1.getRezultat();
InnyObiekt obiekt2 = new InnyObiekt();
obiekt2.setJakasWartosc(rezultatPierwszegoZapytania);
Komunikat k2 = new Komunikat();
k2.wyslij(obiekt2);
jLabel_Wynik.setText(k2.getRezultat());
Komunikat.pokazCosWGUISwiadczaceOPracyWTle(false);
}).start();
});
public class Komunikat {
private int rezultat;
public void wyslij(Object zapytanie) {
jakasMetodaRealizujacaKomunikacjeZSerwerem();
}
public int getRezultat() {
return rezultat;
}
public static void pokazCosWGUISwiadczaceOPracyWTle(boolean trufals) {
// tutaj cuda jak setEnabled, new JFrame albo start/stop
// progressbara.
}
}
Irek Słonina edytował(a) ten post dnia 29.07.09 o godzinie 13:01