Let's make an intra-LAN communication application Part 3 Create a JavaFX event handler / Create a message transmission / reception function by socket communication

Yesterday, I made a Socket reception function using a Java library. (For now, I'm just looking to see if the data was received on the socket on the specified port)

I want to complete the send / receive function today.

Associate an event handler with a JavaFX control

Perform the processing required for linking the event handler in the following steps.

  1. Create a controller class to be linked to FXML.
  2. Associate FXML with the controller class.
  3. Associate FXML control events with controller class methods.

Reference: Oracle --JavaFX: JavaFX Getting Started Guide 6 Creating a User Interface Using FXML (Japanese)

Create a controller class to be linked to FXML.

This seems to be unlimited. It seems that any class can be set, so for the time being Let's set the sender window to MainStage.java created in Let's make a communication application in LAN Part 2.

To be honest, this implementation seems to be subtle. The process of displaying the screen and the process of defining the operation of the screen should be separated.

Associate FXML with the controller class.

Unlike Form, in JavaFX, screen layout / control information is saved in the form of XML, so it cannot be linked to the operation as it is. The solution is simple, just write a class that links the behavior to FXML. That's why.

It seems that there are two ways to do it, so describe each.

How to use SceneBuilder

This is super easy.

  1. Start SceneBuilder and open the FXML file you want to associate.
  2. Click the [Controller] tab at the bottom of the [Document] accordion at the bottom left of the screen to display it. 03_01_ScrnrBuilder_01.jpg
  3. Enter the class you want to associate with the [Controller class] text box. (If you press the [▼] button, the candidate classes will be displayed.) 03_01_ScrnrBuilder_02.jpg

How to modify the FXML file directly

This is also easy.

  1. Just add the parameter fx: controller indicating the control class to the root container (GridPane this time). In particular fx: controller = "Class name of the control class you want to associate (including package name)"

Specifically, it looks like this

MainStage.fxml


<GridPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="kugui.owd.privateMessenger.stage.MainStage">

Associate FXML control events with controller class methods.

After linking the class, link the various control events and the controller class method. This seems to have the following restrictions on the method.

This time I prepared such a method.

MainStage.java


	@FXML
	private void btnSend_Click(ActionEvent event) {
		
		System.out.println( "btnSend is clicked!");
		
		return;
	}

This also describes two ways of setting.

How to use SceneBuilder

This is also simple.

  1. Start SceneBuilder and open the FXML file you want to associate.

  2. Select the controller to which you want to associate the event (this time [Send] button) 03_01_ScrnrBuilder_03.jpg

  3. Click the [Code] tab from the Inspector accordion on the right side of the screen. 03_01_ScrnrBuilder_04.jpg

  4. Enter the method you want to associate in the text box of the related event (this time the OnAction event, which corresponds to the Click event) (Press the [▼] button to display the candidate methods)

03_01_ScrnrBuilder_05.jpg

How to modify the FXML file directly

This is also thin p (ry

  1. Add << corresponding event name (onAction this time) >> = "# << method name you want to associate (class, parentheses not required, # at the beginning is required) >>" to the corresponding control.

Specifically, it looks like this

MainStage.fxml



      <Button mnemonicParsing="false" onAction="#btnSend_Click" text="Send" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER" />

Event handler implementation result confirmation

If you can do so far, check if you can link.

2018y06m15d_065842800.jpg

Get the contents of a text box

After that, if you take the content of the message and the information of the destination and send the socket, the sending function is OK. So let's get the content from the GUI textbox created by JavaFX.

The procedure is as follows

  1. Set the id to the JavaFx control you want to touch.
  2. Declare an object with the same type and name as the control for which the ID is set in the class. (If not public. Add @FXML annotation)

Set the id to the JavaFx control you want to touch.

You have to set the id to be consistent between the FXML and java sources.

There are two ways to set the id.

When setting the ID from SceneBuilder

Shin (ry)

  1. Start SceneBuilder and open the FXML file you want to associate.
  2. Select the controller to which you want to associate the event (this time SendTo text field)
  3. Click [Inspector Accordion]-[Code Tab]
  4. Enter id (object name) in the fx: id text box of the [Identity] item. 2018y06m15d_092733431.jpg

Almost the same as the event handler part above, so the photo is omitted.

When rewriting the FXML file directly

  1. Add the description of the fx: id attribute to the corresponding control and add the value as the variable name.

Specifically, it looks like this

MainStage.fxml


      <TextArea fx:id="txaMessage" prefHeight="200.0" prefWidth="200.0" promptText="Input send message..." GridPane.rowIndex="1" />

Declare an object with the same type and name as the control for which the ID is set in the class.

I just declare it in the class, but specifically it looks like this.

MainStage.java



Added import: import javafx.scene.control.*;

public class MainStage extends Application {
	
	@FXML private TextArea txaMessage;
	@FXML private TextField txfSendTo;

(Omitted)

Confirmation of acquisition result

Let's println the acquisition result of TextField: txfSendTo (javafx.control.TextField) to input the destination IP address and TextArea: txaMessage (javafx.control.TextArea) to input the message.

Modify the event handler when the button is pressed like this

MainStage.java



	@FXML
	private void btnSend_Click(ActionEvent event) {
		
		System.out.println( "btnSend is clicked!");
		System.out.println( String.format("SendTo : %s ", txfSendTo.getText() ));
		System.out.println( String.format("Message : %s ", txaMessage.getText() ));
		
		return;
	}

The result below.

2018y06m15d_094621205.jpg

Information from the GUI is now OK.

Let's go next.

Create a message sending / receiving function by socket communication

Let's do it in the same way as the previous article. This time, the sending port is not specified. I'm not particular about it.

So let's quickly create a new sending class.

Implemented sending class.

The processing flow looks like this

  1. Make a socket
  2. Establish a TCP connection with the destination (at clientSocket.connect ())
  3. Send a message to the send port via DataOutputStream (this time the string "TestMessage")
  4. Close the socket.

Set targetIP to be set by setTargetIP method.

TxThread.java



package kugui.owd.privateMessenger;

import java.io.*;
import java.net.*;

public class TxThread extends Thread {
	
	private String targetIP;
	
	
	public void run() {
		
		int port = 80;
		int timeout = 10000;
		
		Socket clientSocket = new Socket();
		
		try {
			
			clientSocket.connect(new InetSocketAddress(targetIP, port), timeout);
			
			DataOutputStream dos = new DataOutputStream(clientSocket.getOutputStream());
			dos.writeUTF("TestMessage");
			dos.close();
			
		}catch(IOException ie) {
			
			ie.printStackTrace();
			
		}
		
		try {
			
			clientSocket.close();
			
		}catch(IOException ie) {
			
			ie.printStackTrace();
			
		}
		
		return;
	}
	
	public void setTargetIP(String pIP) {
		targetIP = pIP;
		return;
	}
	
}

It may be out of place, but it may be a diversion of RxThread.java created in the previous article.

Operation check

Let's see if the data is actually delayed to the specified IP address. In the previous state, I only saw "Did you access the specified port?" I added a little reception processing.

The following functions have been added.

RxThread.java


package kugui.owd.privateMessenger;

import java.io.*;
import java.net.*;

public class RxThread extends Thread {

	public void run() {

		int port = 80; //For test.
		int timeout = 1000;
		ServerSocket sSocket;

		try {

			sSocket = new ServerSocket(port);
			sSocket.setSoTimeout(timeout);
			
			System.out.println(String.format("start listening port %d", port));

			while (true) {

				try {
					int length = 0;
					
					DataInputStream dis = new DataInputStream(sSocket.accept().getInputStream());
					
					System.out.println(String.format("IP %d port %d : socket accept", sSocket.getInetAddress().toString() ,port));

					
					while(true) {
						
						byte[] buffer = new byte[1024];
						length = dis.read(buffer);
						if( length > 0 ) {
							
							System.out.print(new String(buffer));
							
						}else {
							break;
						}
						
					}
					
					
					dis.close();

				} catch (SocketTimeoutException se) {

					if (interrupted() == true) {

						break;

					} else {

						/* no operation */

					}
				}
			}

		} catch (IOException ioE) {

			ioE.printStackTrace();

		}

		System.out.println("finished");

		return;
	}

}

If you connect to localhost from your browser in this state, it will look like this.

03_01_HTTP_REQUEST.jpg

I was able to confirm that the contents of the HTTP request were displayed properly.

Next, enter localhost in the SendTo text field and press the send button to get this result. 2018y06m15d_115147834.jpg

It seems that the message has been received.

__ However, there is a problem that the message is occasionally interrupted. __ ~~ Well, if you can't extract information from the receiving socket under the current situation, you can finish reading without asking questions. ~~

So, after a short break, the rest of the work

I will do it. Let's break it once. The working time this time was 05:20:20.

Recommended Posts

Let's make an intra-LAN communication application Part 3 Create a JavaFX event handler / Create a message transmission / reception function by socket communication
Let's make a communication application in LAN Part 2 Display a window using JavaFX / Wait for socket reception
Let's make a communication application in LAN Part 4 Set information in JavaFX control / Call JavaFX screen from thread
I tried to make a message function of Rails Tutorial extension (Part 1): Create a model
I tried to make a message function of Rails Tutorial extension (Part 2): Create a screen to display
Let's make a LAN communication application Part 1 New project creation using Maven and Java entry point
Let's create a TODO application in Java 4 Implementation of posting function
Let's make a book management web application with Spring Boot part1
Let's make a book management web application with Spring Boot part3
Let's create a TODO application in Java 6 Implementation of search function
Let's create a TODO application in Java 8 Implementation of editing function
Let's make a book management web application with Spring Boot part2