基本窗体的设计
一、前言
注:本系列几篇文章展示了“简易版飞鸽传书”的编写过程,该程序可实现在局域网内收发文字信息和文件的功能。希望可以通过这个样例让读者对java网络编程和IO编程有所了解。其中,主要参考了李刚的《疯狂java讲义》,有一些代码直接拷贝自该书第17章,头像图片来源于网络,特此说明。另外需要说明的是:本程序在jdk1.8下开发,在笔者的局域网环境下测试通过,能实现发送文字消息和传输小文件的功能,但笔者并不能保证能在你的环境下也一定可以测试通过~ O__O “…
本文为该系列文章的第一篇。我们在这一篇中,将实现这个程序的几个窗口,当然在这里我们先是简单地实现它们,在之后的编写过程中可能还会有所修改,之后的所有的类都会是这个过程。首先来看下效果。
登录窗口:
用户登录成功后跳转到好友列表窗口:
当在某个好友头像上双击后将打开一个与该好友聊天的窗口:
二、登录窗口
首先来实现登录窗口。我们可以让它继承一个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