0

I have implemented fft for my school project(tuner), although, im not able to pass calculated frequency to GUI. I tried binding, keyframes, i just cant seem to get a grasp of it, im really new to java.

public class FrequencyBean {

double freq;
private SimpleDoubleProperty value = new SimpleDoubleProperty(this, "value");


public void setValue(double value){
        this.value.set(value);
        System.out.println(value+" set");
    }
public DoubleProperty getDoublePropertyValue(){
    System.out.println("gotvals");
    return value;
}
public FrequencyBean(){
    freq = 10.0;
}

that is part of my controller, also i got reccomended to use something called tight binding or so, which would be abstracting of this class. Is that good for my code?

This is my main controller:

public class Controller implements Initializable{

FrequencyBean fbean;

@FXML
private Label otherFq;

@FXML
private Text frequency;

@FXML
private Text sharpFq;

@FXML
private Rectangle sharp6;

@FXML
private Text flatFq;

@FXML
private Rectangle center_rectangle;

@FXML
private Rectangle sharp1;

@FXML
private Rectangle sharp2;

@FXML
private Rectangle sharp3;

@FXML
private Rectangle sharp4;

@FXML
private Rectangle sharp5;

@FXML
private Text centerFq;

@FXML
private Rectangle flat6;

@FXML
private Rectangle flat5;

@FXML
private Rectangle flat4;

@FXML
private Rectangle flat3;

@FXML
private Rectangle flat2;

@FXML
private Rectangle flat1;

@Override
public void initialize(URL location, ResourceBundle resources) {

    fbean = new FrequencyBean();
    otherFq = new Label();
    frequency = new Text();
    boolean stop = false;
    InputThread input =  new InputThread();
         Task<Void> in = new Task<Void>() {

            @Override
            protected Void call() throws Exception {

                input.run();

                return null;

                }
            };
        Thread th0 = new Thread(in);
        th0.start();


        frequency.textProperty().bind(fbean.getDoublePropertyValue());
}
  • 1
    Never initialize fields annotated with `@FXML` (the whole point of `@FXML` is that they will be created by the `FXMLLoader`). Here you create a new `Text` object, assign it to `frequency`, and never display it, so no matter what you do with changing its `text` the results will never be visible. Remove `frequency = new Text()`. – James_D Mar 09 '17 at 14:50
  • @James_D thanks for the reply. Although all I got was bunch of FXML errors out of nowhere, but I have sorted this out. Anyway, could you possibly provide info on how does DoubleProperty work? It seems to work ok now, but gets stuck when I assign `double` to `DoubleProperty` s set method. – sleepallday Mar 10 '17 at 13:35
  • Sorry, I don't really understand what you are asking. What do you mean by it "gets stuck"? – James_D Mar 10 '17 at 13:37
  • I have set sysouts on certain points, and when my code reaches call of the method with `double` argument, which assigns it to `DoubleProperty` it stops and doesn't execute the following code. I used concurrency, and this is extended in `Task`, so my gui is ok, but code behind is stopped. – sleepallday Mar 10 '17 at 13:41
  • It's throwing an exception, because changing the property causes the UI to update via your binding, and you can't update the UI from a background thread. (Set an `onFailed` handler on your task and do `task.getException().printStackTrace()` in it to see...) – James_D Mar 10 '17 at 13:42
  • I surrounded `input.run` in try/catch block, and you were right. Now what do I need to do to get it up and running? if I used input as a thread so far, and need to get it running like this, what should I do? – sleepallday Mar 10 '17 at 13:55
  • Read, e.g. http://stackoverflow.com/questions/30249493/using-threads-to-make-database-requests, or just [search](http://stackoverflow.com/search?q=%5Bjavafx%5DIllegalStateException++Not+on+FX+Application+Thread) this site for "IllegalStateException Not on FX Application Thread" – James_D Mar 10 '17 at 14:03
  • but the stacktrace I get is `java.lang.NullPointerException at controllers.FrequencyBean.setValue(FrequencyBean.java:15) at models.Input.run(Input.java:97) at controllers.Controller$1.call(Controller.java:92) at controllers.Controller$1.call(Controller.java:1) at javafx.concurrent.Task$TaskCallable.call(Task.java:1423) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.lang.Thread.run(Thread.java:745) ` – sleepallday Mar 10 '17 at 14:23
  • Well then you have a null pointer exception, which you need to fix first – James_D Mar 10 '17 at 14:24

1 Answers1

0

Rewrite your FrequencyBean correctly as a 'JavaFX-Bean':

public class FrequencyBean {

   private SimpleDoubleProperty frequency = new SimpleDoubleProperty();

   /**
   * @param frequency the frequency to set
   */
   public void setFrequency(double value){
        this.frequency.set(value);
   }

   /**
   * @return the frequency as double 
   */
   public double getFrequency(){
        return this.frequency.get();
   }

   /**
   * @return the frequency property
   */
   public DoubleProperty frequencyProperty(){
      return value;
   }
   public FrequencyBean(){
      frequency = 10.0;
   }
}

As Jame_D pointed it out: don't initialize a control annotated with @FXML. Just bind the control in question like so:

...
@FXML 
TextField tf_Frequency;
...

fbean = new FrequencyBean(20.3);
tfFrequency.textProperty().bind(fbean.frequencyProperty().asString("%.2f"));

Note that this is correct if you need a uni-directional binding. There is also a bindBidirectional method.

Meziane
  • 1,586
  • 1
  • 12
  • 22
  • Thanks for the answer, anyway I have solved this with fPropetry used as observable value, using ChangeListener in initialization later. It works, but if there is any reason(say, memory or something) to use binding over listeners in general, Ill be glad to further my education. – sleepallday Apr 11 '17 at 13:53
  • The "raison d'être" of binding is less code: we don't need to add a listner, the binding "embed" a listner. – Meziane Apr 21 '17 at 11:19