1.一步一步写简易版飞鸽传书(一)

基本窗体的设计

一、前言

注:本系列几篇文章展示了“简易版飞鸽传书”的编写过程,该程序可实现在局域网内收发文字信息和文件的功能。希望可以通过这个样例让读者对java网络编程和IO编程有所了解。其中,主要参考了李刚的《疯狂java讲义》,有一些代码直接拷贝自该书第17章,头像图片来源于网络,特此说明。另外需要说明的是:本程序在jdk1.8下开发,在笔者的局域网环境下测试通过,能实现发送文字消息和传输小文件的功能,但笔者并不能保证能在你的环境下也一定可以测试通过~ O__O “…


本文为该系列文章的第一篇。我们在这一篇中,将实现这个程序的几个窗口,当然在这里我们先是简单地实现它们,在之后的编写过程中可能还会有所修改,之后的所有的类都会是这个过程。首先来看下效果。

登录窗口:

 

用户登录成功后跳转到好友列表窗口:

 1.一步一步写简易版飞鸽传书(一)_第1张图片

 

当在某个好友头像上双击后将打开一个与该好友聊天的窗口:

 

 

二、登录窗口

首先来实现登录窗口。我们可以让它继承一个JDialog ,用GridLayout 放上相应的控件即可。需要说明的是我们要在JComboBox 中显示一些头像给用户来选择作为他们自己的头像。另外,点击登录按钮后,要打开一个好友列表的窗口。

 

为了能让JComboBox 显示图片,我们需要实现一个 ListCellRenderer 

 

class IconListRender extends JLabel implements ListCellRenderer{

	
		public Component getListCellRendererComponent(JList list, Object value,
				int index, boolean isSelected, boolean cellHasFocus) {
			// TODO 自动生成的方法存根
		
			 ImageIcon image=null;
			 
	         if (value instanceof Object[]) {
	              Object[] values = (Object[]) value;                 
	              image = (ImageIcon)values[0];
	            }
	            if (image != null) {
	                 
	              this.setIcon(image);
	            }
	            return this;
		}	
	}

头像选择下拉框iconList 的相应代码如下:

private JComboBox iconList;
        //头像选择列表
	    Object[][] icons = {
	    		
	    		{new ImageIcon("icon/0.jpg")},
	    		{new ImageIcon("icon/1.jpg")},
	    		{new ImageIcon("icon/2.jpg")},
	    		{new ImageIcon("icon/3.jpg")},
	    		{new ImageIcon("icon/4.jpg")},
	    		{new ImageIcon("icon/5.jpg")},
	    		{new ImageIcon("icon/6.jpg")},
	    		{new ImageIcon("icon/7.jpg")},
	    		{new ImageIcon("icon/8.jpg")},
	    		{new ImageIcon("icon/9.jpg")},
	    };

iconList = new JComboBox(icons);
iconList.setPreferredSize(new Dimension(224, 40));
iconList.setRenderer(new IconListRender());


我们把头像图片放在icon 目录下,命名为0.jpg 1.jpg ... ... 。这样有个好处是根据getSelectedIndex()方法,就能知道用户选择的是哪个头像。另外,在所有人的好友列表中都会首先放上一个“所有人”,意思是打开一个所有人的聊天窗口实际上就是打开了一个群聊窗口,所有人都可以看到其中的信息。最终的登录窗口代码如下:

 

package com.myipmsg.frame;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;

import com.myipmsg.bean.User;

/**
 * 登录窗口
 * @author ThinkPad
 *
 */
public class LoginFrame extends JDialog {

	/**
	 * 
	 */
	private static final long serialVersionUID = -1578751340255443641L;
	
	private JTextField userNameField;
	private JComboBox iconList;
	private JButton loginBtn;
	
	public LoginFrame(){
		
	    super();
	    setLayout(new GridLayout(3, 1));
	    
	    //用户名输入框
	    userNameField = new JTextField("zhutulang" , 20);
	    userNameField.setPreferredSize(new Dimension(224, 40));
	    add(getPanel("用户名", userNameField));
	    
	    //头像选择列表
	    Object[][] icons = {
	    		
	    		{new ImageIcon("icon/0.jpg")},
	    		{new ImageIcon("icon/1.jpg")},
	    		{new ImageIcon("icon/2.jpg")},
	    		{new ImageIcon("icon/3.jpg")},
	    		{new ImageIcon("icon/4.jpg")},
	    		{new ImageIcon("icon/5.jpg")},
	    		{new ImageIcon("icon/6.jpg")},
	    		{new ImageIcon("icon/7.jpg")},
	    		{new ImageIcon("icon/8.jpg")},
	    		{new ImageIcon("icon/9.jpg")},
	    };
	    iconList = new JComboBox(icons);
	    iconList.setPreferredSize(new Dimension(224, 40));
	    iconList.setRenderer(new IconListRender());
	    add(getPanel("头  像", iconList));
	    
	    //登录按钮
	    loginBtn = new JButton("登录");
	    loginBtn.addActionListener(new LoginBtnActionListener(this));
	    JPanel loginPanel = new JPanel();
		loginPanel.add(loginBtn);
		add(loginPanel);
	    
	    pack();
	    setTitle("用户登录");
	    //设置居中显示
	    setLocationRelativeTo(null);
	    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	    setVisible(true);
	}
	
	
	// 工具方法,该方法将一个字符串和组件组合成JPanel对象
	private JPanel getPanel(String name , JComponent jf)
	{
		JPanel jp = new JPanel();
		jp.add(new JLabel(name + ":"));
		jp.add(jf);
		return jp;
	}
	
	
   class IconListRender extends JLabel implements ListCellRenderer{

	
		public Component getListCellRendererComponent(JList list, Object value,
				int index, boolean isSelected, boolean cellHasFocus) {
			// TODO 自动生成的方法存根
		
			 ImageIcon image=null;
			 
	         if (value instanceof Object[]) {
	              Object[] values = (Object[]) value;                 
	              image = (ImageIcon)values[0];
	            }
	            if (image != null) {
	                 
	              this.setIcon(image);
	            }
	            return this;
		}	
	}
	
    // 定义登录按钮事件监听器
	class LoginBtnActionListener implements ActionListener
	{
		private LoginFrame loginFrame;
		public LoginBtnActionListener(LoginFrame loginFrame)
		{
			this.loginFrame = loginFrame;
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			//显示好友列表窗口
			FriendListFrame friendListFrame = new FriendListFrame();
			friendListFrame.addUser(new User(userNameField.getText(), iconList.getSelectedIndex()+".jpg"));
			loginFrame.setVisible(false);
		}
	}
	
	public static void main(String[] args) {
		
		LoginFrame loginFrame = new LoginFrame();
	}
}

三、好友列表窗口

这部分主要是将登录用户的头像、用户名绘制在窗体上,代码基本上就是拷贝自李刚的《疯狂java讲义》了,主要是实现一个 ListCellRenderer 。在这个类中涉及到了用户类 User User类的代码如下:

package com.myipmsg.bean;

/**
 * 用户类
 * @author ThinkPad
 *
 */
public class User {

	//用户名
	private String name;
	//用户头像
	private String icon;
	
	public User(String name,String icon){
		this.name = name;
		this.icon = icon;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getIcon() {
		return icon;
	}
	public void setIcon(String icon) {
		this.icon = icon;
	}
}


好友列表窗口类如下:
package com.myipmsg.frame;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;

import com.myipmsg.bean.User;

/**
 * 好友列表窗口
 * @author ThinkPad
 *
 */
public class FriendListFrame extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5200439274745789016L;
	private DefaultListModel<User> listModel = new DefaultListModel<>();
	//好友列表
	private JList<User> friendList = new JList<>(listModel);
	
	// ------对ListModel的包装------
	// 向好友列表中添加用户
	public void addUser(User user)
	{
		listModel.addElement(user);
	}
	// 从好友列表中删除用户
	public void removeUser(int pos)
	{
		listModel.removeElementAt(pos);
	}
	// 获取该好友列表的用户数量
	public int getUserNum()
	{
		return listModel.size();
	}
	
	
	public  FriendListFrame(){
		
		super("好友列表");
		addUser(new User("所有人", "all.jpg"));
		friendList.setCellRenderer(new ImageCellRenderer());
		friendList.addMouseListener(new ShowChatFrameListener());
		add(new JScrollPane(friendList));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds( (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()-200, 5, 200 , 600);
		setVisible(true);
	}
	
	//实现JList上的鼠标双击事件的监听器
	class ShowChatFrameListener extends MouseAdapter{
		
		public void mouseClicked(MouseEvent e)
		{
			//双击
			if(e.getClickCount() >= 2){
				
				User user = friendList.getSelectedValue();
				ChatFrame chatFrame = new ChatFrame(user);			
			}
		}
	}
		
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FriendListFrame frame =  new FriendListFrame();	
	}

}



//定义用于改变JList列表项外观的类
class ImageCellRenderer extends JPanel
	implements ListCellRenderer<User>
{
	private ImageIcon icon;
	private String name;
	// 定义绘制单元格时的背景色
	private Color background;
	// 定义绘制单元格时的前景色
	private Color foreground;
	@Override
	public Component getListCellRendererComponent(JList list
		, User user , int index
		, boolean isSelected , boolean cellHasFocus)
	{
		// 设置图标
		icon = new ImageIcon("icon/" + user.getIcon());
		name = user.getName();
		// 设置背景色、前景色
		background = isSelected ? list.getSelectionBackground()
			: list.getBackground();
		foreground = isSelected ? list.getSelectionForeground()
			: list.getForeground();
		// 返回该JPanel对象作为单元格绘制器
		return this;
	}
	// 重写paintComponent方法,改变JPanel的外观
	public void paintComponent(Graphics g)
	{
		int imageWidth = icon.getImage().getWidth(null);
		int imageHeight = icon.getImage().getHeight(null);
		g.setColor(background);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setColor(foreground);
		// 绘制好友图标
		g.drawImage(icon.getImage() , getWidth() / 6 - imageWidth / 2
			, 10 , null);
		g.setFont(new Font("SansSerif" , Font.BOLD , 18));
		// 绘制好友用户名
		g.drawString(name, getWidth() / 6 + imageWidth
			, 10 + imageHeight/2 );
	}
	// 通过该方法来设置该ImageCellRenderer的最佳大小
	public Dimension getPreferredSize()
	{
		return new Dimension(60, 80);
	}
}

四、聊天窗口

聊天窗口类也很简单,现在只放了发送消息的相应控件。代码如下:

package com.myipmsg.frame;

import java.awt.BorderLayout;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

import com.myipmsg.bean.User;

/**
 * 聊天窗口
 * @author ThinkPad
 *
 */
public class ChatFrame extends JDialog {

	// 聊天信息区
	JTextArea msgArea = new JTextArea(12 , 45);
	// 聊天输入区
	JTextField chatField = new JTextField(30);
	// 发送聊天信息的按钮
	JButton msgSendBtn = new JButton("发送信息");

    public ChatFrame(User user){
    	super();
    	setTitle("和"+user.getName()+"聊天中");
    	setIconImage(new ImageIcon("icon/"+user.getIcon()).getImage()); 
		msgArea.setEditable(false);
		add(new JScrollPane(msgArea));
		JPanel buttom = new JPanel();
		buttom.add(new JLabel("输入信息:"));
		buttom.add(chatField);
		buttom.add(msgSendBtn);
		add(buttom , BorderLayout.SOUTH);
		// 将Ctrl+Enter键和"send"关联
		chatField.getInputMap().put(KeyStroke.getKeyStroke('\n'
			, java.awt.event.InputEvent.CTRL_MASK) , "send");
		// 将"send"与sendAction关联
		//chatField.getActionMap().put("send", sendAction);
		setVisible(true);
		setLocationRelativeTo(null);
		pack();
    }
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        new ChatFrame(new User("sss", ""));
	}
}

所有代码可在此处下载: http://download.csdn.net/detail/zhutulang/9207885

你可能感兴趣的:(1.一步一步写简易版飞鸽传书(一))