📄 onlinefrm.java
字号:
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.Timer;
public class OnLineFrm {
private ObjectInputStream input;
private JFrame f;
private int WIDTH,HEIGHT,SCREEN_WIDTH;
private Point currentBaseP;
private Timer hideListTimer;
private Thread refreshListTimer;
private volatile boolean isHided = false;
private volatile boolean isRunning = true;
private JList list;
private DefaultListModel model;
private MyCellRenderer render;
private JCheckBox hideCheckBox;
private JButton setMyInfoBtn;
private Vector<ClientInfo> infoVector;
private String qqNumber,ip,port,nickname;
private JPopupMenu popMenu;
//用于接收信息,转发给相应的窗口
private DatagramSocket socketR;
private DatagramPacket packetR;
public OnLineFrm(ObjectInputStream input,
String qqNumber,String ip,String port){
init(input,qqNumber,ip,port);
buildGUI();
hookEvent();
initWorkThread();
}
private void buildGUI(){
this.f = new JFrame("猫猫2007");
this.f.setIconImage(new ImageIcon("Icon/titleIcon.gif").getImage());
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
this.SCREEN_WIDTH = size.width;
this.WIDTH = size.width/4;
this.HEIGHT = size.height;
this.f.setSize(WIDTH,HEIGHT);
this.f.setResizable(false);
this.currentBaseP = new Point(size.width*3/4,0);
this.f.setLocation(size.width*3/4,0);
/**
* 添加在线列表
*/
model = new DefaultListModel();
list = new JList(model);
render = new MyCellRenderer();
list.setCellRenderer(render);
list.setBackground(Color.pink);
JScrollPane scrP = new JScrollPane(list);
this.f.add(scrP,BorderLayout.CENTER);
/**
* 自动隐藏按钮
*/
hideCheckBox= new JCheckBox("自动隐藏",false);
this.setMyInfoBtn = new JButton("个人设置");
/**
* 初始化按钮面板
*/
JPanel btnP1 = new JPanel();
btnP1.setBackground(Color.CYAN);
btnP1.setLayout(new FlowLayout(FlowLayout.LEFT));
btnP1.add(hideCheckBox);
JPanel btnP2 = new JPanel();
btnP2.setBackground(Color.CYAN);
btnP2.setLayout(new FlowLayout(FlowLayout.RIGHT));
btnP2.add(this.setMyInfoBtn);
JPanel btnP = new JPanel();
btnP.setLayout(new GridLayout(1,2));
btnP.add(btnP1);
btnP.add(btnP2);
this.f.add(btnP,BorderLayout.SOUTH);
/**
* 用于查看资料和聊天的PopupMenu
*/
initPopMenu();
this.f.setVisible(true);
}
private void acceptWorkTrd(){
//监听指定端口接收数据
try {
this.socketR = new DatagramSocket(9000);
} catch (SocketException e)
{}
new Thread(new Runnable(){
public void run(){
acceptMsg();
}
}).start();
}
private void acceptMsg(){
while(isRunning){
try{
//一次最多能传送500字
byte[] buffer = new byte[1024];
packetR = new DatagramPacket(buffer,buffer.length);
this.socketR.receive(packetR);
MyUtilities.playSound("Sound/msg.wav");
String s = new String(buffer,0,packetR.getLength());
StringTokenizer st = new StringTokenizer(s,"$");
new TalkFrm(st.nextToken(),st.nextToken(),st.nextToken());
Thread.sleep(2000);
}catch(Exception e)
{}
}
}
private void initPopMenu(){
this.popMenu = new JPopupMenu();
Action viewInfoAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
popMenu.setVisible(false);
}
};
viewInfoAction.putValue(Action.NAME, "查看资料");
popMenu.add(viewInfoAction);
popMenu.add(new JSeparator());
Action deleteAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
refreshList(list.getSelectedIndex());
popMenu.setVisible(false);
}
};
deleteAction.putValue(Action.NAME, "删除");
Action talkAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
popMenu.setVisible(false);
}
};
talkAction.putValue(Action.NAME, "发送消息");
popMenu.add(deleteAction);
popMenu.add(new JSeparator());
popMenu.add(talkAction);
popMenu.setVisible(false);
popMenu.pack();
}
private void dealTalk(){
//隐藏在线列表
if(!this.hideCheckBox.isSelected()){
this.hideCheckBox.setSelected(true);
}
new TalkFrm((String)this.list.getSelectedValue(),
this.nickname,
this.infoVector.elementAt(
this.list.getSelectedIndex()).ip);
}
private void hookEvent(){
//隐藏列表
this.f.addComponentListener(new ComponentAdapter(){
public void componentMoved(ComponentEvent e){
currentBaseP = e.getComponent().getLocation();
}
});
this.f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
/**
* 退出前通知服务器
*/
try{
new ObjectOutputStream(
new Socket(
ip,Integer.parseInt(port)).getOutputStream()
).writeObject(new Message("下线",qqNumber));
}catch(Exception ex)
{}
isRunning = false;
if(hideListTimer.isRunning()){
hideListTimer.stop();
}
System.exit(0);
}
});
this.list.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
//双击
if(e.getClickCount() == 2){
/**
* 建立聊天窗口前先隐藏在线列表
*/
dealTalk();
}//右击
else if(e.getClickCount()==1&&SwingUtilities.isRightMouseButton(e)){
/**
* 显示PopMenu
*/
for(int i=0;i < model.size();++i){
if(list.getCellBounds(i, i+1).contains(e.getPoint())){
list.setSelectedIndex(i);
}
}
if(!infoVector.elementAt(list.getSelectedIndex()).number.equals(qqNumber)){
popMenu.show(list,e.getPoint().x,e.getPoint().y);
}
}
}
});
this.hideCheckBox.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED){
if(!hideListTimer.isRunning()){
hideListTimer.restart();
}else{
hideListTimer.start();
}
}
else if(e.getStateChange() == ItemEvent.DESELECTED){
hideListTimer.stop();
}
}
});
}
private void initWorkThread() {
/*原本要实现为隐藏服务的
* try {
Robot r = new Robot();
r.mouseMove(this.currentBaseP.x+this.WIDTH/2,
this.currentBaseP.y+this.HEIGHT/2);
} catch (AWTException e) {
e.printStackTrace();
}*/
/*初始化为自动隐藏服务的Timer线程*/
this.hideListTimer = new Timer(1500, new ActionListener(){
public void actionPerformed(ActionEvent e){
resetLocation(MouseInfo.getPointerInfo().getLocation()
);
}
});
this.hideListTimer.setRepeats(true);
this.refreshListTimer = new Thread(new Runnable(){
public void run(){
refreshList();
}
});
refreshListTimer.start();
}
private void init(ObjectInputStream input,
String qqNumber,String ip,String port){
this.infoVector = new Vector<ClientInfo>();
this.qqNumber = qqNumber;
this.ip = ip;
this.port = port;
this.input = input;
}
/**
* 从服务器接收列表信息并更新
*/
private void refreshList(){
while(this.isRunning){
try {
Object o = this.input.readObject();
if(o instanceof ClientInfo){
/*更新在线列表*/
ClientInfo info = (ClientInfo)o;
this.render.iconNames.add(info.iconName);
this.model.addElement(info.nickName);
if(info.number.equals(qqNumber)){
//记录当前用户的昵称
this.nickname = info.nickName;
}
/*保存好友资料*/
this.infoVector.add(info);
}else if(o instanceof Message){
Message m = (Message)o;
if(m.sysMsg.equals("有人下线")){
//防止用户已经删除了该用户啦!
for(int i=0;i < this.infoVector.size();++i){
if(this.infoVector.elementAt(i).number.equals(m.msg)){
refreshList(i);
break;
}
}
}
}
Thread.sleep(2000);
} catch (Exception e)
{}
}
}
/**
* 列表的某项被删除后,更新这一项后面的ClientInfo中各项Index
*/
private void refreshList(int index){
//更新List
this.model.remove(index);
this.render.iconNames.remove(index);
this.list.repaint();
//更新用户信息
this.infoVector.remove(index);
}
/**
* 负责隐藏和显示列表
*/
private void resetLocation(Point currentPoint){
//显示的时候鼠标移出了List
if(!isHided){
if(!(new Rectangle(this.currentBaseP,
new Dimension(WIDTH,HEIGHT)
).contains(currentPoint))){
//隐藏
hideFrm();
}
}else{
if(isNeedShow(currentPoint)){
showFrm();
}
}
}
private void hideFrm(){
Point newP = null;
if(currentBaseP.x<0)
newP = new Point(1-WIDTH,0);
else if(currentBaseP.x> this.SCREEN_WIDTH-WIDTH)
newP = new Point(this.SCREEN_WIDTH-1,0);
else
newP = new Point(currentBaseP.x,1-this.HEIGHT);
this.f.setLocation(newP);
this.isHided = true;
}
private void showFrm(){
if(this.currentBaseP.x <0){
this.currentBaseP.x =0;
}else if(this.currentBaseP.x>this.SCREEN_WIDTH-this.WIDTH){
this.currentBaseP.x = this.SCREEN_WIDTH-this.WIDTH;
}
currentBaseP.y =0;
this.f.setLocation(currentBaseP);
this.isHided = false;
}
private boolean isNeedShow(Point p){
return (p.x==0&¤tBaseP.x<=0)||
(p.y==0&¤tBaseP.x>=0)||
(p.x==this.SCREEN_WIDTH-1&¤tBaseP.x >(this.SCREEN_WIDTH-this.WIDTH)
);
}
private class MyCellRenderer extends JPanel implements ListCellRenderer {
private Vector<String> iconNames;
private JLabel iconLab;
public MyCellRenderer(){
iconNames = new Vector<String>();
iconLab = new JLabel();
this.setLayout(new FlowLayout(FlowLayout.LEFT));
this.add(iconLab);
}
public Component getListCellRendererComponent(
JList list,
Object value, // value to display
int index, // cell index
boolean isSelected, // is the cell selected
boolean cellHasFocus) // the list and the cell have the focus
{
this.iconLab.setIcon(
new ImageIcon("PersonIcon/"+iconNames.elementAt(index)));
this.iconLab.setText(value.toString());
this.iconLab.setIconTextGap(10);
if(isSelected){
this.setBackground(Color.cyan);
}else{
this.setBackground(list.getBackground());
}
return this;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -