JavaFX 将数据从 Arduino 传递到 jfxtras gauge

JavaFX pass data to jfxtras gauge from Arduino

首先让我感谢您提供的任何指导。我一直在绞尽脑汁让这个工作,并且一直在这里查看许多线程,但没有运气。我是 Java 和 JavaFX 的新手,但有 C# 背景,主要是 MSFT visual Studio。我目前正在使用 IntelliJ 作为我的 IDE 平台。

我想做的(我认为)很简单:我正在读取并成功解析来自 Arduino 控制器的数据,该控制器正在读取传感器,为功率计提供读数。我的数据以逗号分隔的形式存在,并且有一个缓冲的 reader 和串行端口事件,我能够解析一行,string.split 它,然后放入一个数组中(转换为双倍的)。这部分运行良好,正如您从代码中看到的那样,我也将其毫无问题地打印到控制台:

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>

这是控制器:(目前什么都没有,因为我不想有任何按钮或类似的东西...只是显示数据:

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 {

 }

我尝试了不同的组合,但仪表拒绝显示从串行端口读取的数据。我认为这可能与 GUI 位于与主线程不同的线程(一直在搜索和阅读)上有关,但对于我来说,我无法弄清楚如何更改我的代码以使这个看似简单的任务工作。我只想让仪表显示数据……我知道我可能在做一些完全愚蠢的事情……但是我想不通。

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

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

请帮忙!!!!

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

在控制器中创建带注释的字段并定义一个方法来设置它:

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 方法是从后台线程调用的,因此您应该将对控制器的调用包装在 Platform.runLater(...):

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();
        }
    }

}