Java聊天室2.0版本

仿照了网上的代码和思路对之前的1.0版本进行了修改,按别人的界面和思路来写代码巨难受

设计到的一些知识点

1.swing界面:

BorderLayout与FlowLayout的区别

BorderLayout类:

BorderLayout将版面分成EAST(东),SOUTH(南),WEST(西),NORTH(北),CENTER(中),五个区域块,并语序将组件放在指定的区域块内,因为将组件放入BorderLayout版面内会造成组件变形,所以不适合加入JButton(按钮)这类组件,而比较合适JPanel(面板);

FlowLayout类

FlowLayout的配置方式也是从左到右,从上到下,排列,如果窗口宽度足够,会将所有的语速放在同一行;如果宽度不够,自动换行。FlowLayout默认组件居中对齐,也可以按照需求左对齐或者右对齐 ,加入FlowLayout版面的组件也是按照顺序摆放的,所以也无法直接指定要摆放的位置。组价不会变形可以加入JButton这类组件。

另外还有个GridLayout(int rows, int cols, int hgap, int vgap) :

创建具有指定行数、列数以及组件水平、纵向一定间距的网格布局

JOptionPane类的使用:主要用于弹出提示框

showConfirmDialog():确认对话框 
showInputDialog():输入对话框 
showMessageDialog():消息对话框 
showOptionDialog():选择对话框

2.针对窗口事件的监听类

addWindowListener(new WindowAdapter() { //窗口关闭后断开连接
            @Override
            public void windowClosing(WindowEvent e) {
                try {
                    if (socket != null)
                        socket.close();
                    if (inputStream!= null)
                        inputStream.close();
                    if (outputStream != null)
                        outputStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        })

addWindowListener:添加窗口事件监听器

WindowAdapter是抽象类,它是专门用于接收窗口事件的抽象适配器,由于抽象类不能被实例化,所以上面的程序中,创建了一个继承于WindowAdapter的匿名内部类,注意:继承并不需要重载所有方法,只要针对想处理的进行重写就可。

3.JTextArea中setText与append的区别

setText是让文本框显示你要的信息  而append则是在不改变文本框内容的基础上再它后面添加你的信息
textArea.setEditable(false);//设置为不可操作

如果要让文本框显示自己的信息则要用append

4.flush()方法的作用:flush()方法将输入流和输出流中的缓冲进行刷新,使缓冲区中的元素即时做输入和输出,而不必等缓冲区满

代码如下

客户端页面

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
//import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class TwoClientView extends JFrame implements ActionListener,KeyListener,Runnable{
	private JTextArea textArea;
	private JTextField textfield,tfname;
	private JButton btnSend,btnId;
	private JLabel label;
	private JPanel jp1, jp2;
	public boolean isConnect=false;
	private Socket socket=null;
	private DataInputStream inputStream=null;
	private DataOutputStream outputStream=null;
	private JScrollPane scrollpane;
	private static TwoClientView view;
	 public JTextArea getTextArea() {
	        return textArea;
	    }

	    public DataInputStream getInputStream() {
	        return inputStream;
	    }
	    public DataOutputStream getOutputStream() {
	        return outputStream;
	    }
	    public static void main(String[] args) {
			view=new TwoClientView();
			TwoServiceView.clientviews.add(view);//添加到客户端集合中
			Thread thread=new Thread(view);
			thread.start();
		}
	    public TwoClientView(){
	    initView();
        try {
            socket = new Socket("localhost", 9090);//连接本地服务器

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

	    private void initView() {
	    	textArea=new JTextArea(20,20);
	    	 textArea.setEditable(false);//设置为不可操作
	    	textfield=new JTextField(15);
	    	scrollpane=new JScrollPane(textArea);//可以自动产生滚动轴
	    	textfield.addKeyListener(this);
	    	btnSend=new JButton("发送");
	    btnSend.addActionListener(this);
	    	label=new JLabel("昵称");
	    	tfname=new JTextField(8);
	    	jp1=new  JPanel();
	    	jp2=new JPanel();
	    	jp1.add(label);
	    	jp1.add(tfname);
	    	tfname.setText("用户0");
	    	jp1.setLayout(new FlowLayout(FlowLayout.CENTER));
	    	jp2.add(textfield);
	    	jp2.add(btnSend);
	    	jp2.setLayout(new FlowLayout(FlowLayout.CENTER));
	    	
	    	this.add(jp1,BorderLayout.NORTH);
	    	this.add(scrollpane, BorderLayout.CENTER);
	    	this.add(jp2, BorderLayout.SOUTH);
	    	this.setTitle("聊天室");
	    	setSize(500, 500);
	    	setLocation(450, 150);
	    	setVisible(true);
	    	setDefaultCloseOperation(EXIT_ON_CLOSE);
	    	this.addWindowListener(new WindowAdapter() {
	    		public void windowClosing(WindowEvent e) {
	    		try {
	    			if(socket!=null) socket.close();//如果socket本身就是null关不关也就无所谓了
	    			if(inputStream!=null) inputStream.close();
	    			if(outputStream!=null) outputStream.close();
	    		}catch(IOException e1){
	    			e1.printStackTrace();
	    		}
	    		}
			});
	    }
	    public void actionPerformed(ActionEvent e) {
	    	if(e.getSource()==btnSend) {
	    		SendMsg();
	    	}
	    }
	    

	    
	    private void SendMsg() {
	    	try {
	    		String str=textfield.getText();
	    		if(!str.equals("")) {
	    			textfield.setText("");
	    			textArea.append(tfname.getText()+":\n"+str+"\n");//将内容发到自身的area上
	    			outputStream=new DataOutputStream(socket.getOutputStream());
	    			outputStream.writeUTF(tfname.getText()+"#"+str);//将内容读入文件输出流
	    			outputStream.flush();//清空缓存数据
	    		}
	    	}
	    	catch(IOException e) {
	    		e.printStackTrace();
	    	}
	    }
	    
	    @Override
	    public void keyPressed(KeyEvent arg0) {//也可使用回车键发送
	        if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
	            SendMsg();
	        }
	    }

	    @Override
	    public void keyReleased(KeyEvent arg0) {

	    }

	    @Override
	    public void keyTyped(KeyEvent arg0) {

	    }

	    @Override
	    
	   
	    public void run() {
	    	try {
	    		inputStream=new DataInputStream(socket.getInputStream());
	    		while(true) {
	    			String []s=inputStream.readUTF().split("#");
textArea.append(s[0]+":\n"+s[1]+"\n");//用于向其他用户发送信息
	    		}
	    	}
	    	catch(IOException e) {
	    		e.printStackTrace();
	    	}
	    }
}

2服务端页面

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;



public class TwoServiceView extends JFrame implements ActionListener{
	private JButton btnOpen,btnStop;
	private JLabel label;
	private TwoService service=null;
	public static ArrayList<TwoClientView> clientviews=new ArrayList<>();
	private static TwoServiceView view;
	public static TwoServiceView getView() {
		return view;
	}
	public static void main(String[] args) {
		view=new TwoServiceView();
	}
	public TwoServiceView() {
		initView();
	}
	private void initView() {
		btnOpen=new JButton("打开服务器");
		btnStop=new JButton("关闭服务器");
		btnStop.setEnabled(false);
		btnOpen.addActionListener(this);
		btnStop.addActionListener(this);
		label=new JLabel("服务器停止工作");
		add(label);
		add(btnOpen);
		add(btnStop);
		setTitle("服务器");
		setLayout(new GridLayout(3, 1,0,10));
		setSize(300, 300);
		setLocation(450, 450);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}
	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==btnOpen) {
			open();
		}else {
			stop();
		}
	}
	public void open() {
		service=new TwoService();
		Thread thread=new Thread(service);
		thread.start();
		label.setText("服务器正在运行");
		btnOpen.setEnabled(false);
		btnStop.setEnabled(true);
	}
	public void stop() {
		label.setText("服务器已关闭");
		btnOpen.setEnabled(true);
		btnStop.setEnabled(false);
		try {
			synchronized (TwoClientMannager.sockets) {//使用sockets作为同步监视器,任何线程进入同步代码块必须先
				for(TwoCharSocket socket:TwoClientMannager.sockets) {//获得对sockets的锁定
					socket.getInputStream().close();
					socket.getOutputStream().close();
				}
				TwoClientMannager.sockets.removeAllElements();//删除集合中的所有客户端信息
			}
			for(TwoClientView view: clientviews) {
				view.getInputStream().close();
				view.getOutputStream().close();
			}
			service.getserviceSocket().close();
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
}

3开启服务端连接

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JOptionPane;


public class TwoService implements Runnable{//本类用来开启服务端连接
	private ServerSocket serversocket=null;
	public ServerSocket getserviceSocket() {
		return serversocket;
	}
public void run() {
	try {
		serversocket=new ServerSocket(9090);//建立与客户端的连接
		while(true) {
			Socket socket=serversocket.accept();
			JOptionPane.showMessageDialog(TwoServiceView.getView(), "客户端连接端口", "TIP", JOptionPane.INFORMATION_MESSAGE);
			TwoCharSocket chatsocket=new TwoCharSocket(socket);
			TwoClientMannager.sockets.add(chatsocket);//每建立起一个连接就将它添加到连接集合中去
			Thread thread=new Thread(chatsocket);//启动线程不断接收客户端信息
			thread.start();//开启服务端连接通道
		}
	}catch(IOException e) {
		e.printStackTrace();
		System.out.println("服务器关闭");
	}
}
}

4。开启客户端连接

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class TwoCharSocket implements Runnable{开启服务端连接
private Socket socket=null;
private DataInputStream inputStream = null;
private DataOutputStream outputStream = null;
public DataInputStream getInputStream() {
	return inputStream;
}
public DataOutputStream getOutputStream() {
    return outputStream;
}
public TwoCharSocket(Socket socket) {
	this.socket=socket;
	 try {
         inputStream = new DataInputStream(socket.getInputStream());
         outputStream = new DataOutputStream(socket.getOutputStream());
     } catch (IOException e) {
         e.printStackTrace();
     }
}
public void send(String str) {//用于将所有的信息输入服务端的输出流
	try {
		outputStream.writeUTF(str);
		outputStream.flush();
	}catch(IOException e) {
		e.printStackTrace();
	}
	
}
public void run() {
	String accept=null;
	while(true) {
		try {
			accept=inputStream.readUTF();
			TwoClientMannager.sendAll(this, accept);
		}catch(IOException e) {
			TwoClientMannager.sockets.remove(this);
		}
	}
}
}

5向所有客户端发送信息的操作

import java.util.Vector;

public class TwoClientMannager {//用于向所有客户端发送信息的操作
private TwoClientMannager() {
}
public static Vector<TwoCharSocket> sockets=new Vector<>();
public static void sendAll(TwoCharSocket charSocket,String send) {
	for(TwoCharSocket s:sockets) {
		if(!charSocket.equals(s)) {//判断是不是自身
			s.send(send);
		}
	}
}
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值