Modyfikowanie GUI w innym wątku JavaFX

Odpowiedz Nowy wątek
2014-12-20 15:37
0

Hej,
Mam dwie aplikacje: serwerowa i kliencka. Serwer jest zwykłą aplikacją serwerową a Klient aplikacją JavaFX. Potrzebuje w Kliencie sprawdzać np. co 50ms czy nadszedł komunikat i jeśli tak wykonać funkcje zmieniającą tekst przycisku tzn. button.setText("STH"); Robię to tak:

Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    Platform.runLater(createListener());                
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MainController.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }                
            }
        }); 

Gdzie metoda createListener(); zwraca interfejs Runnable w którym zmieniam tekst przycisku.
Niestety gdzie nowy wątek wywoła metodę start() moja aplikacja się zawiesza i nie mogę jej nawet przeciągnąć...
Co źle robię?

Pozostało 580 znaków

2014-12-20 15:41
0

A co się dzieje w tym kodzie odpalanym przez Platform.runLater? Podaj kod.

Spróbuj, dla testów zwracać pustego Runnable w createListener() i zobacz czy ci się będzie interfejs przycinał. Jeśli nie to znaczy, że błąd jest właśnie w tym co tworzyłeś (oryginalnie) przez createListener().


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 2x, ostatnio: Wibowit, 2014-12-20 15:42

Pozostało 580 znaków

2014-12-20 16:01
0

Tak znalazłem problem... Ale nie wiem czym jest spowodowany. Wywołując metodę readObject() na obiekcie klasy ObjectInputStream metoda się nie kończy, dlatego program 'stoi'...

Pozostało 580 znaków

2014-12-20 16:10
0

readObject() prawdopodobnie czeka, aż nadejdą dane.

W wątku GUI zmieniaj tylko GUI, nie rób nic więcej. Jeśli masz zczytać dane z sieci to zrób to w innym wątku, przetwórz na docelowy format, a w wątku GUIowym (czyli poprzez Platform.runLater) zmień tylko stan GUI na podstawie gotowych danych.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2014-12-20 16:15
0

Tak wiem to, myślałem tylko że jeśli nie ma danych to funkcja się zakończy...

Pozostało 580 znaków

2014-12-20 16:22
0

Strumienie w Javie zawsze czekają na dane i zwracają wynik. Żeby było tak jak chcesz to strumienie musiałyby próbować deserializacji za każdym razem jak wywołujesz metodę readObject(), potencjalnie powodując wielokrotną deserializację tego samego obiektu. Dokładając do tego fakt iż niektóre obiekty mogą mieć spory zserializowany rozmiar i złożoność, to ogólna złożoność pamięciowa (na bufory) i obliczeniowa (na wielokrtoną deserializację) deserializacji mogłaby urosnąć do ogromnych rozmiarów. Bez próby deserializacji nie da się stwierdzić czy przyszło wystarczająco dużo danych by z nich złożyć obiekt.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2014-12-20 16:34
0

Kwestia jest taka że wiem jak duże dane tam są... Czy istnieje sposób żeby sprawdzić czy strumień nie jest pusty i wtedy pobrać dane a jeśli nie to pominąć pobieranie?

Pozostało 580 znaków

2014-12-20 16:41
0

Lepiej zrobisz jeśli po prostu będziesz wczytywał poza wątkiem GUI. Możesz posłużyć się wbudowanymi w Javę kolejkami jak np LinkedBlockingQueue do przesyłania obiektów między wątkami, możesz iść na całość i użyć Akka.io, możesz też posłużyć się klasami Service czy Task z JavyFX: http://docs.oracle.com/javase[...]lity-tutorial/concurrency.htm Zacznij od tej ostatniej opcji.

Staraj się robić w wątku GUI jak najmniej, bo potem cały interfejs będzie w kółko lagował.

A odpowiadając wprost na twoje pytanie: żeby coś takiego osiągnąć musiałbyś zrobić coś a'la BufferedInputStream tyle że z dodatkową funkcją która mówi czy jest wystarczająco dużo danych by wczytać cały obiekt. Następnie ten twój Stream musiałby pośredniczyć między InputStreamem wczytującym z sieci, a InputStreamem deserializującym obiekty, a ty musiałbyś odpytywać zarówno strumień deserializujący obiekty jak i ten twój buforujący dane. Wydaje mi się jednak, że takie rozwiązanie działałoby i tak gorzej niż te przedstawione wcześniej, bo najszybciej dostaniesz dane jak będziesz na nie cały czas czekał i je natychmiast wczytywał - dzięki temu żaden pośredni bufor nie będzie się blokował.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 5x, ostatnio: Wibowit, 2014-12-20 16:50

Pozostało 580 znaków

2014-12-20 19:38
0

Super, dzięki, działa ;) Jeszcze mam jedno pytanie nie tworząc nowego posta. Korzystam w swoich dwóch aplikacjach z klas Socket i ServerSocket. Lokalnie wszystko działa, a jeśli chciałbym postawić serwer u siebie na komputerze i aby znajomy podłączył się od siebie to co muszę podać w hoście, IP? I czy jest jakaś różnica czy mam wew. czy zew. IP?

Pozostało 580 znaków

2014-12-20 20:32
0

Java pod spodem korzysta ze standardowych socketów, takich samych jakie dostałbyś w C, C++, Pythonie czy czymkolwiek. Stąd pytanie nie jest o Javę, a o sieci.

Podałeś mało szczegółów, a ja nie jestem zresztą sieciowcem. Prawdopodobnie musisz zorientować się jakie masz publiczne IP, czy jesteś za NATem lub czymś podobnym, czy masz poblokowane lub sforwardowane porty i jak u ciebie działa firewall czy reguły bezpieczeństwa Javy.

IP wewnętrzne jest widoczne tylko z wewnątrz. Zewnętrzne jest widoczne z zewnątrz :] A wewnątrz czego? Wewnątrz podsieci, np VPNa, sieci lokalnej, whatever.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.

Pozostało 580 znaków

2014-12-20 23:55
0

Ok, dzięki za pomoc ;)

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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