GUIイベント駆動とマルチスレッド
簡単なチャットプログラム
実はこの例は、見かけ上スレッドの使用を隠すことは可能だが、マルチユーザのゲームに向けて Runnable インタフェースを明示的に実装するようにしている。2つのソースからなる。まず、メインクラスのTalkをみてみる。接続を確立するのが役目。サーバとクライアントはソースを共有している。
package talk; import java.net.ServerSocket; import java.net.Socket; public class Talk { public static final int PORT = 12000; public static final int SERVER = 0; public static final int CLIENT = 1; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int role = SERVER; String hostname = null; TalkPanel tp; Socket soc = null; if (args.length == 1 ){ role = CLIENT; hostname = args[0]; } try { if (role == SERVER) { ServerSocket tempSoc = new ServerSocket(PORT); soc = tempSoc.accept(); tempSoc.close(); } else{ soc = new Socket(hostname, PORT); } tp = new TalkPanel(role, soc); new Thread(tp).start(); } catch (Exception e) { System.out.println("error"); System.exit(-1); } } }
もうひとつは TalkPanel クラス。コンストラクタは接続済のソケットを受け取り、このインスタンスはソケットの入力を監視するスレッドを走らせる。合わせてGUI部品のイベントにも対処する。
package talk; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import javax.swing.*; public class TalkPanel implements Runnable { Socket soc; BufferedReader reader; PrintWriter writer; JFrame frame; JTextField peerMessage; JTextField myMessage; JButton send; String title; protected TalkPanel(int role, Socket soc) { this.soc = soc; if(role == Talk.SERVER) title = "Server"; else title = "Client"; frame = new JFrame(title); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setSize(500, 200); peerMessage = new JTextField("相手のメッセージがここに表示されます",40); peerMessage.setEditable(false); myMessage = new JTextField("あたなのメッセージをここに入力します",40); myMessage.setEditable(true); send = new JButton("Send"); send.setSize(100, 20); frame.getContentPane().setLayout(new FlowLayout()); frame.getContentPane().add(peerMessage); frame.getContentPane().add(myMessage); frame.getContentPane().add(send); send.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // TODO Auto-generated method stub writer.println(myMessage.getText()); writer.flush(); System.out.println("sent"); myMessage.setText(""); } }); frame.setVisible(true); } @Override public void run() { // TODO Auto-generated method stub try { reader = new BufferedReader(new InputStreamReader( soc.getInputStream())); writer = new PrintWriter(new OutputStreamWriter( soc.getOutputStream())); } catch (Exception e) { System.exit(-1); } System.out.println("run"); while (true) { try { String line = reader.readLine(); System.out.println("received"); peerMessage.setText(line); } catch (Exception e) { System.exit(-1); } } } }