Objektum átadása másik osztályba JavaFX

Objektum átadása másik osztályba JavaFX
2019-04-08T06:47:54+02:00
2019-04-09T06:55:49+02:00
2022-10-15T21:36:37+02:00
Fulop9
Sziasztok!

Controller osztályból próbálok átadni egy label-t, sikertelenül. 2 féle képen próbálkoztam eddig, konstruktorban átadtam, ami Pane-eknél működött is, de label-eknél nem.. és öröklődéssel bár az csak egy próbálkozás volt.

public class Controller implements Initializable { @FXML protected Label you_label; ....//egyéb kódok Thread szal = new Thread(new Tasker(you_label)); //itt adom át konstruktornak szal.start(); } public class Tasker extends Controller implements Runnable { Label you; public Tasker(Label you) { this.you = you; } @Override public void run() { //you_label.setText("ghj"); //öröklődéssel próba you.setText("fdsg"); //konstruktorral átadva próba /* idő megvalósítás próba, de több label-t szeretnék még itt átírni később. for(int i =15;i>=0;i--){ time.setText("00:"+i); //Sleep(1000); } */ } public void Sleep(int a) { try { Thread.sleep(a); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } Amilyen hibákat kaptam eddig: //(konstruktor átadásnál hiba): you.setText("fdsg"); Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4 at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279) at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423) at javafx.scene.Parent$2.onProposedChange(Parent.java:367) at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113) at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108) at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575) at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204) at com.sun.javafx.scene.control.skin.LabelSkin.handleControlPropertyChanged(LabelSkin.java:49) at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$70(BehaviorSkinBase.java:197) at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55) at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89) at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182) at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81) at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103) at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110) at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:144) at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49) at javafx.beans.property.StringProperty.setValue(StringProperty.java:65) at javafx.scene.control.Labeled.setText(Labeled.java:145) at Game.Tasker.run(Tasker.java:50) at java.lang.Thread.run(Unknown Source) //(öröklődésnél hiba):you_label.setText("ghj"); Exception in thread "Thread-4" java.lang.NullPointerException at Game.Tasker.run(Tasker.java:48) at java.lang.Thread.run(Unknown Source)
Mutasd a teljes hozzászólást!

  • A JavaFX-hez nem értek, de a hibaüzenetek alapján megvan ugyanaz a megkötése, mint más UI frameworköknek: a UI elemeket csak egy adott szálból lehet módosítani. Rövidtávú megoldás gyors Google alapján az, hogy használod a Platform.runLater() metódust. Ez a metódus a megadott kódot átküldi a UI szálnak, hogy futtassa le, ha majd "ráér" (értsd: feldolgozta a felhasználó által addig kezdeményezett interakciókat). Valahogy így:

    @Override public void run() { Platform.runLater( () -> you.setText("fdsg") ); }
    Így persze nincs sok értelme, hogy a háttérszálad tol egy runLater()-t aztán ki is lép, de tudsz köré ciklust és várakozást rakni, hogy már legyen értelme. Mondjuk amiatt, hogy a módosulás késlekedhet, ha animációt csinálsz így, az nem feltétlen lesz szép egyenletes.

    Hosszú távon amúgy se jó ötlet mindenféle másik osztálynak átadni UI elemeket, amiket azok majd piszkálnak kedvükre. Jó eséllyel egy nagy katyvasz lesz a végeredmény, amit nem tudsz átlátni és karban tartani. A játék állapotát külön osztályban kéne megvalósítani, aztán a UI-ért felelős kódnak ez alapján az állapot alapján kéne felépítenie a UI-t. Így a játéklogikáért felelős kód el lenne választva a felülettől, és könnyebb lenne a kódot felfogni, módosítani.
    Mutasd a teljes hozzászólást!
  • Ehhez mit szólsz: updating a label
    Mutasd a teljes hozzászólást!
  • Hosszú távú jól átlátható megoldást szeretnék.

    "A játék állapotát külön osztályban kéne megvalósítani, aztán a UI-ért felelős kódnak ez alapján az állapot alapján kéne felépítenie a UI-t."



    De itt nem teljesen értem mit írtál, hogyan kellene ezt megvalósítanom? Mert adatbázist nem akarok, nézetért ugye az FXML file felelős, a Controller osztály pedig az "interakció"-kért felelős, de várakoztatni pedig csak másik szálból tudtam eddig.
    Mutasd a teljes hozzászólást!
  • Ezek szerint akkor hallottál már a Model-View-Controller mintáról. Na, a játékot megvalósító osztály (illetve neki egy példánya) lenne a Model. Ő tárolna olyan dolgokat, mint hogy mi a főszereplő karakter pozíciója, hol vannak éppen és merre mennek az ellenségek stb. Ide kerülhetnek a metódusok, amivel a főszereplő valamilyen irányba elmozdul, meg ami a szimulációt előrelépteti valamennyi idővel. Ha jól csinálod, akkor a játéklogikát le lehet futtatni a felhasználói felület nélkül is, ami például tesztelésnél nagyon hasznos lehet. A játéklogika egyáltalán nem tud semmit a felületről, ami a külvilág felé mutatja az állapotot és ami az irányítást megvalósítja.

    Mert adatbázist nem akarok

    Ez nem tudom honnan jött, én nem írtam egy szót se adatbázisokról 
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd