[英]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.