[英]Get Real-time data from server socket and Display it in javafx
您好,我需要从我创建的服务器套接字中获取一些数据并将其显示在 javafx 应用程序 fx 应用程序中,即显示器每 250 毫秒刷新一次数据,服务器每 2 秒发送一次数据
我的代码/计划主要有 3 个部分
1.服务器每2秒生成数据并发送到端口
2. Clint 代码从服务器获取数据并更新其全局变量
3. 每 250 毫秒调度执行器访问 clint 中的全局变量并更新文本字段
// 遗憾的是这似乎不起作用
我总是启动服务器然后 clint 然后运行应用程序
所以我写的代码如下
服务器代码
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;
import java.util.concurrent.TimeUnit;
public class Server {
public static void main(String[] args) throws IOException, InterruptedException {
Socket socket;
try (ServerSocket serverSocket = new ServerSocket(5555)) {
System.out.println("A");
socket = serverSocket.accept();
System.out.println("B");
if(socket.isConnected())System.out.println("Connected");
DataOutputStream dout=new DataOutputStream(socket.getOutputStream());
while (socket.isConnected()) {
String T=DataStructureMaker();
dout.writeUTF(T);
System.out.println(T);
TimeUnit.SECONDS.sleep(2);
dout.flush();
}
}
socket.close();
}
public static String DataStructureMaker()
{
float RV_Phase=0,RI_Phase=0,RI_Grid=0,RV_Grid=0;String s="";
DecimalFormat df = new DecimalFormat("#.00");
s="";
RV_Phase=Float.parseFloat(df.format((Math.random()*10)));
s=s+Float.toString(RV_Phase)+"#";
RI_Phase=Float.parseFloat(df.format((Math.random()*10)));
s=s+Float.toString(RI_Phase)+"#";
RI_Grid=Float.parseFloat(df.format((Math.random()*10)));
s=s+Float.toString(RI_Grid)+"#";
RV_Grid=Float.parseFloat(df.format((Math.random()*10)));
s=s+Float.toString(RV_Grid)+"#";
return s;
}
}
克林特代码是
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class Clint {
public static String RV_Grid;
public static String RI_Grid;
public static String RI_Phase;
public static String RV_Phase;
public static void main(String[] args) throws IOException, InterruptedException {
Socket s=new Socket("localhost",5555);
String S;
DataInputStream dIn=new DataInputStream(s.getInputStream());
while (s.isConnected()) {
S=dIn.readUTF();
setData(S);
}
}
public static void setData(String S) // Decryt data and set global values
{
char[] A=S.toCharArray();
int HC=0;
String R="";
if(A.length>2)
for(char x:A)
{
if(x=='#')
{
switch(HC)
{
case 0:
HC++;
RV_Phase=R;
R="";
break;
case 1:
HC++;
RI_Phase=R;
R="";
break;
case 2:
HC++;
RI_Grid=R;
R="";
break;
case 3:
HC++;
RV_Grid=R;
R="";
break;
}
}else{
R=R+x;
}
}
}
}
最后是我的 fxml controller
import java.util.ResourceBundle;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextField;
public class FXMLDocumentController implements Initializable {
@FXML
private TextField Text1;
@FXML
private TextField Text2;
@FXML
private TextField Text3;
@FXML
private TextField Text4;
static ScheduledExecutorService scheduledExecutorService;
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(() -> {
setData();
}, 0, 250, TimeUnit.MILLISECONDS);
}
public void setData()
{
Text1.setText(Clint.RI_Grid);
Text2.setText(Clint.RI_Phase);
Text3.setText(Clint.RV_Grid);
Text4.setText(Clint.RV_Phase);
}
}
上面的代码有我的程序加密、解密发送接收和显示所需的所有无能数据
以下代码旨在服务于两个目的:
一个是为提出的问题展示一个mre 。
另一个是使用客户端接收到的数据动态更新 GUI 的解决方案。
该代码并非旨在展示如何正确实现客户端和服务器。
MRE有几点需要注意:
1. 它不应该代表您的特定应用程序,而是您要解决的重点特定问题。
2.应该是M:去掉所有不重要的。 最低限度。
3.应该是R:重现问题。
4. 应该是完整的。独立于数据库、文件或其他不可用的资源。
5.它应该易于使用(复制过去)。
为了使用客户端接收到的数据动态更新 GUI,我使用了共享的 model,它由客户端更新。
如果使用绑定在 GUI 中反映 model 中的任何更改。
为了简单和易于使用,我将 controller、model、服务器和客户端都放在一个文件FXMLDocumentController.java
:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.ResourceBundle;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
public class FXMLDocumentController implements Initializable {
private static int PORT_NUMBER = 5555;
@FXML
private TextField text1;
@FXML
Button stopButton, startButton;
private ScheduledExecutorService scheduledExecutorService;
private Model model;
private Client client;
private Server server;
@Override
public void initialize(URL url, ResourceBundle rb) {
startButton.setDisable(false);
stopButton.setDisable(true);
scheduledExecutorService = Executors.newScheduledThreadPool(2);
model = new Model();
text1.textProperty().bind(model.getTextProperty());
}
private void startServer(){
try {
server = new Server(PORT_NUMBER);
server.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void startClient(){
try {
client = new Client(PORT_NUMBER, model);
client.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void start(){
scheduledExecutorService.submit(() -> startServer());
scheduledExecutorService.submit(() -> startClient());
startButton.setDisable(true);
stopButton.setDisable(false);
}
public void stop(){
client.stop();
server.stop();
scheduledExecutorService.shutdown();
stopButton.setDisable(true);
}
}
class Model {
private final ReadOnlyStringWrapper textProperty;
Model() {
textProperty = new ReadOnlyStringWrapper();
}
synchronized void setText(String s){
Platform.runLater(()->textProperty.set(s));
}
ReadOnlyStringWrapper getTextProperty(){
return textProperty;
}
}
class Server {
private final int portNumber;
private volatile boolean stop = false;
private static long REFRESH_TIME = 2;
Server(int portNumber) {
this.portNumber = portNumber;
}
void start() throws IOException {
Socket socket;
try (ServerSocket serverSocket = new ServerSocket(portNumber)) {
socket = serverSocket.accept();
DataOutputStream dout=new DataOutputStream(socket.getOutputStream());
while (socket.isConnected() && ! stop) {
dout.writeUTF(randomText());
try {
TimeUnit.SECONDS.sleep(REFRESH_TIME);
} catch (InterruptedException ex) {
break;
}
dout.flush();
}
}
}
private String randomText()
{
DecimalFormat df = new DecimalFormat("#.00");
StringBuilder sb = new StringBuilder(df.format(Math.random()*10));
sb.append("#")
.append(df.format(Math.random()*10)) ;
return sb.toString();
}
void stop(){
stop = true;
}
}
class Client {
private final int portNumber;
private final Model model;
private volatile boolean stop = false;
Client(int portNumber, Model model) {
this.portNumber = portNumber;
this.model = model;
}
void start() throws IOException {
Socket socket = new Socket("localhost",portNumber);
DataInputStream dIn=new DataInputStream(socket.getInputStream());
while (socket.isConnected() && ! stop) {
model.setText(dIn.readUTF());
}
socket.close();
}
void stop(){
stop = true;
}
}
FXMLDocument.fxml 使用 controller:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.VBox?>
<VBox alignment="CENTER" prefHeight="113.0" prefWidth="232.0" spacing="10" xmlns="http://javafx.com/javafx/10.0.1"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="fx_tests.FXMLDocumentController">
<TextField fx:id="text1" alignment="CENTER" promptText="Press START " />
<GridPane>
<Button fx:id="startButton" maxWidth="Infinity" onAction="#start" text="START" GridPane.columnIndex="0" />
<Button fx:id="stopButton" maxWidth="Infinity" onAction="#stop" text="STOP" GridPane.columnIndex="2" />
</GridPane>
</VBox>
测试它:
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class FxmlTest extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
Pane root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(null);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.