简体   繁体   English

从服务器套接字获取实时数据并显示在 javafx

[英]Get Real-time data from server socket and Display it in javafx

Hello I need to get Some data from a server socket i created and display it in a javafx application fx application ie the display refresh the data every 250ms, and server sends data every 2 seconds您好,我需要从我创建的服务器套接字中获取一些数据并将其显示在 javafx 应用程序 fx 应用程序中,即显示器每 250 毫秒刷新一次数据,服务器每 2 秒发送一次数据

My code/plan have mainly 3 Parts我的代码/计划主要有 3 个部分
1. The server generates the data and sends it to the port every 2 sec 1.服务器每2秒生成数据并发送到端口
2. The Clint code gets the data from the server and updates its global variables 2. Clint 代码从服务器获取数据并更新其全局变量
3. Every 250ms Schedule executioner reach out to the global varibles in clint and update the text fields 3. 每 250 毫秒调度执行器访问 clint 中的全局变量并更新文本字段
// Sadly this doesn't seems to work // 遗憾的是这似乎不起作用
i always starts server then clint then runs the application我总是启动服务器然后 clint 然后运行应用程序

so the Codes i written are as follows所以我写的代码如下

Server Code服务器代码

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

The clint code is克林特代码是

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

and Finally my fxml controller最后是我的 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);
    }       
}

The Above code have All impotent data needed for my program Encryption, Decryption Send Receive and Display上面的代码有我的程序加密、解密发送接收和显示所需的所有无能数据

The code following is aimed to serve two purposes:以下代码旨在服务于两个目的:
The one is to demonstrate an mre for the question asked.一个是为提出的问题展示一个mre
The other being a solution for dynamic update the GUI with data received by the client.另一个是使用客户端接收到的数据动态更新 GUI 的解决方案。
The code is not aimed to show how to correctly implement the client and server.该代码并非旨在展示如何正确实现客户端和服务器。

There are a few things to note about MRE: MRE有几点需要注意:
1. It should not represent your specific application but a focused specific problem you are trying to solve. 1. 它不应该代表您的特定应用程序,而是您要解决的重点特定问题。
2. It should be M: remove all what is not essential. 2.应该是M:去掉所有不重要的。 Bare minimum.最低限度。
3. It should be R: reproduce the problem. 3.应该是R:重现问题。
4. It should be complete.Independent on data-base, files or other unavailable resources. 4. 应该是完整的。独立于数据库、文件或其他不可用的资源。
5. It should be easy to use (copy-past). 5.它应该易于使用(复制过去)。

To dynamically update the GUI with data received by the client, I used a shared model, that it is updated by the client.为了使用客户端接收到的数据动态更新 GUI,我使用了共享的 model,它由客户端更新。
Any change in the model ifs reflected in the GUI by using binding.如果使用绑定在 GUI 中反映 model 中的任何更改。

For simplicity and ease of use I have the controller, the model, the server and the client all in one file FXMLDocumentController.java :为了简单和易于使用,我将 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;
    }
}

The controller is used by FXMLDocument.fxml: 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>

Test it with:测试它:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM