Lassen Sie uns eine In-LAN-Kommunikationsanwendung erstellen. Teil 3 Erstellen eines JavaFX-Ereignishandlers / Erstellen einer Nachrichtenübertragungs- / Empfangsfunktion durch Socket-Kommunikation

Gestern habe ich eine Socket-Empfangsfunktion mit einer Java-Bibliothek erstellt. (Im Moment schaue ich nur, ob der Socket am angegebenen Port die Daten empfangen hat.)

Ich möchte heute die Sende- / Empfangsfunktion abschließen.

Verknüpfen Sie einen Ereignishandler mit einem JavaFX-Steuerelement

Die zum Verknüpfen des Ereignishandlers erforderliche Verarbeitung wird in den folgenden Schritten ausgeführt.

  1. Erstellen Sie eine Controller-Klasse, die mit FXML verknüpft werden soll.
  2. Ordnen Sie der Controller-Klasse FXML zu.
  3. Verknüpfen Sie FXML-Steuerungsereignisse mit Controller-Klassenmethoden.

Referenz: Oracle - JavaFX: JavaFX - Erste Schritte 6 Erstellen einer Benutzeroberfläche mit FXML (Japanisch)

Erstellen Sie eine Controller-Klasse, die mit FXML verknüpft werden soll.

Dies scheint unbegrenzt zu sein. Es scheint, dass jede Klasse vorerst festgelegt werden kann Stellen Sie das Absenderfenster auf die Zielklasse von MainStage.java ein, die in Lassen Sie uns eine Kommunikationsanwendung in LAN Teil 2 erstellen erstellt wurde.

Um ehrlich zu sein, scheint diese Implementierung subtil zu sein. Der Prozess der Anzeige des Bildschirms und der Prozess der Definition der Funktionsweise des Bildschirms sollten getrennt werden.

Verknüpfen Sie FXML mit der Controller-Klasse.

Im Gegensatz zu Form speichert JavaFX Bildschirmlayout- / Steuerungsinformationen in Form von XML, sodass es nicht wie es ist mit Vorgängen verknüpft werden kann. Die Lösung ist einfach: Schreiben Sie einfach eine Klasse, die die Aktion mit FXML verknüpft. Deshalb.

Es scheint, dass es zwei Möglichkeiten gibt, also beschreiben Sie jede.

Verwendung von SceneBuilder

Das ist super einfach.

  1. Starten Sie SceneBuilder und öffnen Sie die FXML-Datei, die Sie zuordnen möchten.
  2. Klicken Sie auf die Registerkarte [Controller] unten im Akkordeon [Dokument] unten links auf dem Bildschirm, um es anzuzeigen. 03_01_ScrnrBuilder_01.jpg
  3. Geben Sie die Klasse, der Sie zuordnen möchten, in das Textfeld [Controller-Klasse] ein. (Wenn Sie die Taste [▼] drücken, werden die Kandidatenklassen angezeigt.) 03_01_ScrnrBuilder_02.jpg

So ändern Sie die FXML-Datei direkt

Das ist auch einfach.

  1. Fügen Sie einfach den Parameter fx: controller, der die Steuerungsklasse angibt, zum Stammcontainer hinzu (diesmal GridPane). Speziell fx: controller = "Klassenname der Steuerungsklasse, die Sie zuordnen möchten (einschließlich Paketname)"

Insbesondere sieht es so aus

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">

Verknüpfen Sie FXML-Steuerungsereignisse mit Controller-Klassenmethoden.

Verknüpfen Sie nach dem Verknüpfen der Klassen die verschiedenen Steuerungsereignisse und die Steuerungsklassenmethoden. Dies scheint die folgenden Einschränkungen für die Methode zu haben.

Diesmal habe ich eine solche Methode vorbereitet.

MainStage.java


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

Dies beschreibt auch zwei Arten der Einstellung.

Verwendung von SceneBuilder

Das ist auch einfach.

  1. Starten Sie SceneBuilder und öffnen Sie die FXML-Datei, die Sie zuordnen möchten.

  2. Wählen Sie den Controller aus, dem Sie das Ereignis zuordnen möchten (diesmal die Schaltfläche [Senden]). 03_01_ScrnrBuilder_03.jpg

  3. Klicken Sie im Inspector-Akkordeon auf der rechten Seite des Bildschirms auf die Registerkarte [Code]. 03_01_ScrnrBuilder_04.jpg

  4. Geben Sie die Methode, die Sie zuordnen möchten, in das Textfeld des zugehörigen Ereignisses ein (diesmal das OnAction-Ereignis, das dem Click-Ereignis entspricht). (Wenn Sie die Taste [▼] drücken, werden die Kandidatenmethoden angezeigt.)

03_01_ScrnrBuilder_05.jpg

So ändern Sie die FXML-Datei direkt

Dies ist auch dünn

  1. Fügen Sie dem entsprechenden Steuerelement den << entsprechenden Ereignisnamen hinzu (diesmal onAction) >> = "# << Methodenname, den Sie zuordnen möchten (Klasse, Klammern nicht erforderlich, # am Anfang erforderlich) >>".

Insbesondere sieht es so aus

MainStage.fxml



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

Bestätigung des Ergebnisses der Implementierung des Ereignishandlers

Wenn Sie dies bisher tun können, prüfen Sie, ob Sie es verknüpfen können.

2018y06m15d_065842800.jpg

Rufen Sie den Inhalt des Textfelds ab

Wenn Sie danach den Inhalt der Nachricht und die Informationen des Ziels übernehmen und den Socket senden, ist die Sendefunktion in Ordnung. Lassen Sie uns den Inhalt aus dem von JavaFX erstellten GUI-Textfeld abrufen.

Das Verfahren ist wie folgt

  1. Stellen Sie die ID auf das JavaFx-Steuerelement ein, das Sie berühren möchten.
  2. Deklarieren Sie ein Objekt in der Klasse, das denselben Typ und Namen wie das Steuerelement hat, für das die ID festgelegt ist. (Wenn nicht öffentlich. @ FXML-Annotation hinzufügen)

Stellen Sie die ID auf das JavaFx-Steuerelement ein, das Sie berühren möchten.

Die ID muss für die Konsistenz zwischen der FXML- und der Java-Quelle festgelegt werden.

Es gibt zwei Möglichkeiten, die ID festzulegen.

Beim Festlegen der ID in SceneBuilder

Shin (ry)

  1. Starten Sie SceneBuilder und öffnen Sie die FXML-Datei, die Sie zuordnen möchten.
  2. Wählen Sie den Controller aus, dem Sie das Ereignis zuordnen möchten (diesmal Textfeld SendTo).
  3. Klicken Sie auf [Inspector Accordion] - [Code Tab].
  4. Geben Sie id (Objektname) in das Textfeld fx: id des Elements [Identität] ein. 2018y06m15d_092733431.jpg

Fast das gleiche wie im obigen Event-Handler-Teil, daher wird das Foto weggelassen.

Beim direkten Umschreiben der FXML-Datei

  1. Fügen Sie dem entsprechenden Steuerelement die Beschreibung des Attributs fx: id hinzu und fügen Sie den Wert als Variablennamen hinzu.

Insbesondere sieht es so aus

MainStage.fxml


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

Deklarieren Sie ein Objekt in der Klasse, das denselben Typ und Namen wie das Steuerelement hat, für das die ID festgelegt ist.

Ich erkläre es nur in der Klasse, aber speziell sieht es so aus.

MainStage.java



Import hinzugefügt: Javafx importieren.scene.control.*;

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

(Weggelassen)

Bestätigung des Akquisitionsergebnisses

Verwenden Sie println, um die Erfassungsergebnisse von TextField: txfSendTo (javafx.control.TextField) zur Eingabe der Ziel-IP-Adresse und TextArea: txaMessage (javafx.control.TextArea) zur Eingabe der Nachricht auszugeben.

Ändern Sie den Ereignishandler, wenn die Schaltfläche wie folgt gedrückt wird

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

Das Ergebnis unten.

2018y06m15d_094621205.jpg

Informationen von der GUI sind jetzt in Ordnung.

Lass uns als nächstes gehen.

Erstellen Sie eine Nachrichtensende- / Empfangsfunktion durch Socket-Kommunikation

Machen wir es genauso wie im vorherigen Artikel. Diesmal ist der Sendeport nicht angegeben. Ich bin nicht besonders darüber.

Erstellen wir also schnell eine neue Sendeklasse.

Sendeklasse implementiert.

Der Verarbeitungsablauf sieht folgendermaßen aus

  1. Machen Sie eine Steckdose
  2. Stellen Sie eine TCP-Verbindung mit dem Ziel her (unter clientSocket.connect ()).
  3. Senden Sie eine Nachricht über DataOutputStream an den Sendeport (diesmal die Zeichenfolge "TestMessage").
  4. Schließen Sie die Steckdose.

Legen Sie targetIP fest, das mit der setTargetIP-Methode festgelegt werden soll.

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

Es ist möglicherweise fehl am Platz, aber es kann eine Umleitung von RxThread.java sein, die im vorherigen Artikel erstellt wurde.

Funktionsprüfung

Mal sehen, ob die Daten tatsächlich auf die angegebene IP-Adresse verzögert sind. Im vorherigen Status wurde nur "Haben Sie auf den angegebenen Port zugegriffen?" Angezeigt. Ich habe eine kleine Empfangsverarbeitung hinzugefügt.

Die folgenden Funktionen wurden hinzugefügt.

RxThread.java


package kugui.owd.privateMessenger;

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

public class RxThread extends Thread {

	public void run() {

		int port = 80; //Zum 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;
	}

}

Wenn Sie in diesem Zustand über den Browser eine Verbindung zu localhost herstellen, sieht dies folgendermaßen aus.

03_01_HTTP_REQUEST.jpg

Ich konnte bestätigen, dass der Inhalt der HTTP-Anforderung ordnungsgemäß angezeigt wurde.

Geben Sie als Nächstes localhost in das Textfeld SendTo ein und klicken Sie auf die Schaltfläche Senden, um dieses Ergebnis zu erhalten. 2018y06m15d_115147834.jpg

__ Es besteht jedoch das Problem, dass die Nachricht gelegentlich unterbrochen wird. __ __ ~~ Wenn Sie in der aktuellen Situation keine Informationen aus der Empfangsbuchse extrahieren können, können Sie das Lesen beenden, ohne Fragen zu stellen. ~~

Also nach einer kurzen Pause der Rest der Arbeit

Ich werde das machen. Lass es uns einmal brechen. Die Arbeitszeit war diesmal 05:20:20.

Recommended Posts

Lassen Sie uns eine In-LAN-Kommunikationsanwendung erstellen. Teil 3 Erstellen eines JavaFX-Ereignishandlers / Erstellen einer Nachrichtenübertragungs- / Empfangsfunktion durch Socket-Kommunikation
Lassen Sie uns eine Kommunikationsanwendung in LAN Teil 2 erstellen. Zeigen Sie ein Fenster mit JavaFX an / Warten Sie auf den Socket-Empfang
Lassen Sie uns eine Kommunikationsanwendung in LAN Teil 4 erstellen. Informationen in JavaFX-Steuerung festlegen / JavaFX-Bildschirm vom Thread aufrufen
Ich habe versucht, eine Nachrichtenfunktion der Rails Tutorial-Erweiterung (Teil 1) zu erstellen: Erstellen Sie ein Modell
Ich habe versucht, eine Nachrichtenfunktion für die Erweiterung Rails Tutorial (Teil 2) zu erstellen: Erstellen Sie einen Bildschirm zum Anzeigen
Lassen Sie uns eine Kommunikationsanwendung in LAN Teil 1 erstellen. Neue Projekterstellung mit Maven und Java Entry Point
Lassen Sie uns eine TODO-App in Java 4 erstellen. Implementierung der Buchungsfunktion
Erstellen wir eine Buchverwaltungs-Webanwendung mit Spring Boot part1
Lassen Sie uns mit Spring Boot part3 eine Webanwendung für die Buchverwaltung erstellen
Lassen Sie uns eine TODO-App in Java 6 erstellen. Implementierung der Suchfunktion
Lassen Sie uns eine TODO-App in Java 8 erstellen. Implementierung von Bearbeitungsfunktionen
Lassen Sie uns mit Spring Boot part2 eine Webanwendung für die Buchverwaltung erstellen