JavaFX передает данные в датчик jfxtras из Arduino

Прежде всего позвольте мне поблагодарить вас за любые рекомендации, которые вы могли бы дать по этому вопросу. Я ломал голову над тем, чтобы заставить это работать, и смотрел на многие темы здесь, без удачи. Я новичок в 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. Вот созданный файл 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 {

 }

Я пробовал разные комбинации, но гаджет отказывается показывать данные, прочитанные из serialPort. Я думаю, что это может быть связано с тем, что GUI находится в потоке, отличном от основного (находился в поиске и чтении), но я не могу понять, как изменить свой код, чтобы сделать эту, казалось бы, простую задачу работающей. Все, что я хочу, это чтобы датчик отображал данные.... Я знаю, что могу делать что-то совершенно глупое... но не могу понять это.

Любые идеи о том, как я мог бы достичь этого?

PS: если я создаю обработчик событий в контроллере, скажем, с помощью кнопки, я могу заставить датчик двигаться с произвольным значением при нажатии кнопки. Почему я не могу сделать то же самое, когда запускается серийное событие????

ПОМОГИТЕ, ПОЖАЛУЙСТА!!!!

1 ответ

Решение

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

}
Другие вопросы по тегам