Let's make a communication application in LAN Part 4 Set information in JavaFX control / Call JavaFX screen from thread

I took a nap (5 hours), so let's resume work.

The LAN communication app is over today, so it's quick (whether it can be done or not)

We will start by repairing the reception process.

Repair of reception processing

Create a display window for incoming messages.

First of all, this. Create a screen to display the received message using JavaFX.

Here is the one made by diverting the send window.

2018y06m15d_224036934.jpg

Call the window on receipt.

I got stuck here.

In this application, I created it with the image that "when a message is received, the received message is displayed in a new window" It is designed to "prepare a listening thread for reception and monitor the port".

At first I was wondering if I should create a screen with the standby thread for reception and display it If you create an instance of javafx.stage.Stage and call the show () method, you will get an IlegalStateException.

↓ Like this

RxThread.java


    (Reception processing)

	Stage stage = new Stage();
	stage.show();

↓ Click here for results

2018y06m16d_001717192.jpg

What is this Exception? When I looked it up, I came across this fact. Says "If you try to operate a JavaFX element from a thread other than the JavaFX application thread, the above exception will be thrown."

So, when I investigated the workaround, it turned out that there is a class called javaFX.platform.

Oracle-JavaFX Documentation Class platform (Japanese)

It seems that JavaFX application will execute it instead by registering a runnnable thread in the runLater () method of this class.

Oh, you can't do new and show ()! Like form. Process to display Stage based on the contents examined at once Rewrite and check the operation.

↓ Change to something like this

RxThread.java


    (Reception processing)

	Platform.runLater( () -> {
		Stage stage = new Stage();
		stage.show();
	});

↓ Here is the result (Stage with a new white window. Resized but quite large at first) 2018y06m16d_004712408.jpg

… Well, in response to this fact It was necessary to change the composition of the screen drawing. (Sigh) It's too dirty if it's made now ...

I fixed it (using it for an hour).

Roughly modified to make something like this

Stage related processing
FXML file for each screen
Stage acquisition class for each screen
Controller class for each screen
Send / receive processing
Thread inheritance class that sends data using socket communication Thread inheritance class that monitors receiving ports and receives data
Normal processing General-purpose thread inheritance class for causing Platform.runLator () to perform Stage drawing processing Class containing entry point

By making the above changes, [Confirm message reception] => [Get received message Stage] => [Request drawing task to Application thread] => [Draw Stage] It is now possible to process.

2018y06m16d_035944134.jpg

Next, I would like to display the received message on this Stage.

Set the value in the GUI controller displayed using JavaFx

It was also tightly packed here. And with a null reference.

Time ... Time ... (frustrated)

The setting method can be realized by the following procedure.

  1. Prepare the process for operating the control in the controller class linked to the GUI.
  2. Get an instance of the controller and call the prepared operation method

How easy it looks once you write it

Prepare the process for operating the control in the controller class linked to the GUI.

This is easy. It's OK if you make an ordinary setter. To treat the control as an object, see "Let's make a LAN communication app Part 3" (https://qiita.com/Shiratori/items/35b0c488f6adbb034cd4) "An object with the same type and name as the control with the ID set. See the item "Declare in class."

Get an instance of the controller and call the prepared operation method

this. I'm completely hooked on this. The points are as follows.

  • The controller instance uses the getController () method of the FXMLLoader class. (Since it is returned as Object type, cast it in the class specified in the controller)
  • The above instance is created when the FXMLLoader.load () method is executed. (If you try to touch it earlier than this, you will get angry with a null reference.

So, for this process, create a getter that returns the value of getControl () with a controller that has the actual state of fxmlLoader. Create a wrapper that receives it in the Stage drawing thread and returns it as it is ... and endlessly ...

It was worth it, and it was successful until the retrieved message was displayed.

2018y06m16d_043800899.jpg

Make it possible to receive messages in a stable manner.

Here is a very sad news. Well, yesterday I was somewhat unconscious (excuse) I put in useless processing and waited for a message.

So, omit unnecessary processing and fix it like this

RxThread.java


			while (length >= 0) {
				byte[] buffer = new byte[1024];
				length = dis.read(buffer);
				sBuffer.append(new String(buffer));
				
			}

  1. Take the buffer area
  2. Update the amount of acquired data
  3. The acquired data is stored in the character string buffer.

That's the process. I wonder if the buffer size could be the value of length.

In the case of socket communication, -1 will be returned when there is no information to acquire. If you run out of information to take, it will come out.

There is no problem so far, so leave this alone. Actually, I tell the other party the amount of data to be transmitted first (to prepare for loss during transmission). Well, this time it's in the LAN. No encryption.

Try to communicate between terminals.

Well, I implemented it all over for the time being (haz), so let's communicate between terminals in the LAN.

For the time being, the result on the development machine (windows 7) and the laptop computer for business (windows 10) looks like this

(It's a very heavy photo because it was taken with a mobile camera. It's more than 70 times larger than the developed main unit (including library)) P_20180616_060205_vHDR_On.jpg

So, alas, I got angry when I tried to boot on Linux. When I looked it up lightly, I found that there was a sun. * Library, so I wonder if there needs to be a little more research. Screenshot from 2018-06-16 06-32-05.png

Since it was built in Java, I want to support various operating systems. Have you achieved your goal for the time being? So far this time. It's a little difficult to use because you hit the IP directly. There is an improvement point ... It's a different function (reopening) I'm worried that / or something is included in the acquired address.

Postscript: It seems that the JavaFX library was not included ... that? Wasn't 1.8 the standard anymore ...? After installing openjfx, it started normally.

Screenshot from 2018-06-16 07-58-48.png

The communication result looks like this. (Displayed in VNC.)

2018y06m16d_080211838.jpg


The operation on the last day ends at 07:41:54. Overall 23:03:51.

What will happen next week?

Oh, I forgot to mention it, but here is GitHub

GitHub - PrivateMessenger https://github.com/Shiratori1218/PrivateMessenger

Recommended Posts