さまざまな TCP ネットワーク デバイスに接続するプログラムを書いています。GUI は JavaFX を使用して作成されます。接続部分全体が独自のパッケージ「Network」に入っています。大まかに説明すると、次のようになります。http://i.stack.imgur.com/PSdsH.jpg
TCP クラスは「NetworkManager」の同期されたリストに保存されます。これらのクラスは、接続に関する情報 (まだ受信したデータの量、ip、mac など) を保持します。Rcv-Thread は常にデータを受信しようとします。
まあ、これは私が望むものです: Rcv-Thread が特定のメッセージを受信するとすぐに、コントローラーを呼び出して何かを実行する必要があります (GUI の更新など)。また、コントローラーは「ネットワーク」モジュールから分離したままにする必要があります->別のプロジェクトで再利用されます。カスタム イベントを通じてこの動作を実現したいと考えています。つまり、TCP-Rcv-Thread はコントローラーに情報を提供できる必要があります。しかし、私はそれをすべて機能させる方法を本当に知りません。私がどこにいるか見てみましょう:
「ネットワーク」モジュールにイベント クラスがあります。
import java.util.EventObject; public class XEvent extends EventObject{ String message; public XEvent(Object source, String message) { super(source); this.message = message; } public String getMessage() { return message; } }
「ネットワーク」モジュールにリスナー クラスがあります。
import java.util.EventListener; public interface XListener extends EventListener{ void handlerMethod1(XEvent event); void handlerMethod2(XEvent event); }
イベントを発生させるために Rcv-Thread を準備しようとしました:
import javax.swing.event.EventListenerList; import java.io.IOException; public class ReceiveDataThread implements Runnable { protected EventListenerList listenerList = new EventListenerList(); } protected void addXListener(XListener xListener) { listenerList.add(XListener.class, xListener); } protected void removeListener(XListener xListener) { listenerList.remove(XListener.class, xListener); } protected void fireHandlerMethod1(String message) { XEvent event = null; Object[] list = listenerList.getListenerList(); for (int i = 0; i < list.length; i += 2) { if (list[i] == XListener.class) { if (event == null) event = new XEvent(this, message); XListener l = (XListener) list[i + 1]; l.handlerMethod1(event); } } } protected void fireHandlerMethod2(String message) { XEvent event = null; Object[] list = listenerList.getListenerList(); for (int i = 0; i < list.length; i += 2) { if (list[i] == XListener.class) { if (event == null) event = new XEvent(this, message); XListener l = (XListener) list[i + 1]; l.handlerMethod2(event); } } } @Override public void run() { String s; while (!stopThread) { s = receiveData(); System.out.println("test"); fireHandlerMethod1(s); } }
コントローラー (このクラスはカスタム イベントに反応する必要があります) は、リスナーを実装します。
public class Controller implements Initializable, XListener { @Override public void handlerMethod1(XEvent event) { System.out.println("Event1: " + event.getMessage()); } @Override public void handlerMethod2(XEvent event) { } }
そして、そこから、私のイベント (私の Rcv-Thread から起動されたもの) が私のコントローラー クラスによって認識されるようにする方法が本当にわかりません。コントローラークラスを介してすべての Rcv-Thread オブジェクトにリスナーを追加する必要があると思います (ButtonListener を使用するときと同じように...) 。問題は、TCP クラスから Rcv-Thread-object の addXListener メソッドにアクセスできないことです - public に設定されていても(ただし、リストから Rcv-Thread-Classes にアクセスできます)。問題についてできる限り読み込もうとしましたが、これを機能させる方法がわかりません。私は何が欠けていますか?
edit1: TCP クラス:
public class TCPClass{
private Thread receiveDataThread;
private String MAC;
private InetAddress IP;
private Socket socket = new Socket();
private int tcpSendPort;
private int timeOut = 10;
private ObjectOutputStream objectOutputStream;
private BufferedReader bufferedReader;
private String connectionStatus = "offline";
public TCPClass(DatagramPacket datagramPacket) {
IP = datagramPacket.getAddress();
setConnectionStatusOnline();
tcpSendPort = 50000 + NetworkManager.getNumberOfConnections();
MAC = extractMac(datagramPacket);
}
public void connect(int tcpPort) {
try {
socket = new Socket(IP, tcpPort, null, tcpSendPort);
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
receiveDataThread = new Thread(new ReceiveDataThread(this));
receiveDataThread.start();
InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
System.out.println("on MAC: " + getMAC() + "\non Device:" + toString());
}
if (socket.isConnected()) {
setConnectionStatusConnected();
}
}
}
NetworkManager は TCPClass のオブジェクトを作成し、connect() メソッドを呼び出します。