JavaFX将数据从Arduino传递到jfxtras仪表

JavaFX将数据从Arduino传递到jfxtras仪表,java,javafx,jfxtras,Java,Javafx,Jfxtras,首先,请允许我感谢您在这方面提供的任何指导。我一直在绞尽脑汁让它工作,并且一直在这里寻找许多线索,没有运气。我不熟悉Java和JavaFX,但有C#背景,主要是在MSFT visual Studio上。我目前使用IntelliJ作为我的IDE平台 我试图做的是(我认为)足够简单:我正在读取并成功解析来自Arduino控制器的数据,该控制器正在读取为功率计提供读数的传感器。我的数据以逗号分隔的形式存在,通过缓冲读取器和串行端口事件,我能够解析一行string.split,然后放入数组(转换为Dou

首先,请允许我感谢您在这方面提供的任何指导。我一直在绞尽脑汁让它工作,并且一直在这里寻找许多线索,没有运气。我不熟悉Java和JavaFX,但有C#背景,主要是在MSFT visual Studio上。我目前使用IntelliJ作为我的IDE平台

我试图做的是(我认为)足够简单:我正在读取并成功解析来自Arduino控制器的数据,该控制器正在读取为功率计提供读数的传感器。我的数据以逗号分隔的形式存在,通过缓冲读取器和串行端口事件,我能够解析一行string.split,然后放入数组(转换为Double后)。这部分工作得很好,正如您从代码中看到的,我也在将其打印到控制台,没有任何问题:

package sample;

import eu.hansolo.enzo.gauge.RectangularGauge;
import gnu.io.*;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.fxml.FXML;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;

import java.io.*;

public class Main extends Application implements SerialPortEventListener {
SerialPort serialPort = null;
private BufferedReader serialIn;
private OutputStream serialOut;
public Double power;


@FXML
private RectangularGauge fwdpower;


@Override
public void start(Stage primaryStage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
    primaryStage.setTitle("Power Meter");
    primaryStage.setScene(new Scene(root, 380, 320));
    primaryStage.show();

    //
    CommPortIdentifier port = CommPortIdentifier.getPortIdentifier("COM60");
    CommPort commPort = port.open(this.getClass().getName(), 2000);
    serialPort = (SerialPort) commPort;
    serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
    serialIn = new BufferedReader(new InputStreamReader((serialPort.getInputStream())));
    serialPort.addEventListener(this);
    serialPort.notifyOnDataAvailable(true);
    //
}


public static void main(String[] args) {
    launch(args);
}

@Override
public void serialEvent(SerialPortEvent e) {
    try {
        String line = serialIn.readLine();
        String[] Values = line.split(",");
        power = Double.parseDouble(Values[1]);
        System.out.println(power / 5);
        }  //This works as expected and shows values on console
        fwdpower.setValue(power/5); //Shows NOTHING! UGHHHH!
    catch (IOException ex) {ex.printStackTrace();
    }
}
现在最难的部分:让我完全沮丧

我现在尝试从jfxtras仪表驱动一个仪表。我已经导入了所有正确的库,并且在scenebuilder中创建了一个非常简单的GUI。以下是创建的XML文件:

<?xml version="1.0" encoding="UTF-8"?>

<?import eu.hansolo.enzo.gauge.RectangularGauge?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>


<GridPane alignment="center" hgap="10" vgap="10"        xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.65"            fx:controller="sample.Controller">
 <columnConstraints>
  <ColumnConstraints />
 </columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
<children>
  <Pane prefHeight="342.0" prefWidth="377.0">
     <children>
        <RectangularGauge fx:id="fwdpower" layoutX="25.0" layoutY="22.0"                         minValue="1.0" />    
     </children>
  </Pane>
  </children>
  </GridPane>
我尝试了不同的组合,但该语言拒绝显示从串行端口读取的数据。我认为这可能与GUI与main处于不同的线程(一直在搜索和阅读)有关,但就我的一生而言,我不知道如何更改代码以使这项看似简单的任务正常工作。我只想让仪表显示数据……我知道我可能在做一些完全愚蠢的事情……但我无法理解这一点

关于如何实现这一点,有什么想法吗

PS:如果我在控制器中创建一个事件处理程序,比如说一个按钮,我可以在按下按钮时使仪表以任意值移动。为什么我不能在串行事件触发时执行相同的操作


请帮帮我

@FXML
-注释字段仅在由
fxmloader
创建的控制器中初始化;您不能简单地在任意对象中注释字段,并期望它由加载程序初始化

在控制器中创建带注释的字段,并定义设置该字段的方法:

package sample;

import eu.hansolo.enzo.gauge.RectangularGauge;
import gnu.io.SerialPortEvent;
import javafx.fxml.FXML;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Controller {

    @FXML
    private RectangularGauge fwdpower ;

    public void setFwdPower(double power) {
        fwdpower.setValue(power);
    }
}
然后,只需获取对控制器的引用并在其上调用该方法。请注意,由于您的
serialEvent
方法是从后台线程调用的,因此您应该在
平台中包装对控制器的调用。runLater(…)


您在JFXtras中使用的库不是JFXtras,而是Enzo。Gerrit的旧计量器库是JFXTRAS2.x的一部分,但他决定将计量器移到自己的库中;恩佐。这就是说,像您这样设置值应该是可行的。您可以尝试将其包装在Platform.runLater(()->fwdpower.setValue(5))中;以确保它在图形线程上运行。也试着用5.0而不是5除法(我总是不确定混合时的doubles和int行为)。谢谢你,特贝诺…是的,谢谢你指出了库的不同,但是,恩佐构建的量具和库似乎工作得很好。在做了一些挖掘之后,我一直在尝试Platform.runLater的组合,但是当我将其添加到串行事件中时,我得到了这样的结果:“重写java.lang.Runnable中的方法……执行会产生一个java.lang.NullPointerException……有什么想法吗?这还不够
package sample;

import eu.hansolo.enzo.gauge.RectangularGauge;
import gnu.io.SerialPortEvent;
import javafx.fxml.FXML;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Controller {

    @FXML
    private RectangularGauge fwdpower ;

    public void setFwdPower(double power) {
        fwdpower.setValue(power);
    }
}
package sample;

import eu.hansolo.enzo.gauge.RectangularGauge;
import gnu.io.*;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.fxml.FXML;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;

import java.io.*;

public class Main extends Application implements SerialPortEventListener {

    SerialPort serialPort = null;
    private BufferedReader serialIn;
    private OutputStream serialOut;


    private Controller controller ;    

    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        Parent root = loader.load();

        controller = loader.getController();

        primaryStage.setTitle("Power Meter");
        primaryStage.setScene(new Scene(root, 380, 320));
        primaryStage.show();

        //
        CommPortIdentifier port = CommPortIdentifier.getPortIdentifier("COM60");
        CommPort commPort = port.open(this.getClass().getName(), 2000);
        serialPort = (SerialPort) commPort;
        serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
        serialIn = new BufferedReader(new InputStreamReader((serialPort.getInputStream())));
        serialPort.addEventListener(this);
        serialPort.notifyOnDataAvailable(true);
        //
    }


    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void serialEvent(SerialPortEvent e) {
        try {
            String line = serialIn.readLine();
            String[] values = line.split(",");
            final double power = Double.parseDouble(values[1]);
            System.out.println(power / 5);
            Platform.runLater(() -> controller.setFwdpower(power/5));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}