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();
}
}
}
首先让我感谢您提供的任何指导。我一直在绞尽脑汁让这个工作,并且一直在这里查看许多线程,但没有运气。我是 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();
}
}
}