[讨论]编写一个类似QQ的聊天的工具的时候遇到难题问题,请高手指点,小弟在此先谢谢了
出现的问题:
1.单击关闭“聊天程序”的窗口怎么与单击“关闭”按钮窗口出现的行为一致?
2.能不能在关闭“字体框”的时候不关闭“聊天程序”的窗口?
3.在改变字体的属性后,我们怎么能马上看到它的效果,需要添加怎样的侦听代码?
4.在这个程序中,为啥要用到线程?
5.我们能不能将字体框不用一个框架而用一个面板来代替,具体代码该怎么改?
6.在我们这个“聊天程序”的主框架中我们要定义一个文本域,一个文本框,一个字体框,和两个按钮,一个是“发送”另一个是“关闭”按钮,在这个地方我们最好用什么布局来完成?买超家世
7.在框架中的布局与面板中的布局有什么不同吗?
8.我们在选择“字体”的时候,作出来的怎么与QQ中选择字体的方式一样,也就是,单击选择字体按钮后弹出字体框,设置好字体后,我们再单击字体按钮它就关闭字体框?
9.ChatServerChatClient类怎么实现在一台电脑上启动一个服务器与一个客户端,而在另一台电脑上只启动一个客户端,从而实现两台电脑的通信
************************************************************************************
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.*;
import java.io.*;
import javax.swing.*;
import javax.swing.border.*; 
import java.applet.*;

public class ChatClient extends Frame{//Frameawt包中
    Socket s = null;
    DataOutputStream dos = null;//为下面connect( )方法设置全局变量
    DataInputStream dis = null;
    private boolean bConnected = false;
    TextArea ta = new TextArea( );//相当于Frame的两个成员变量
    TextField tf = new TextField( );
    Button bon1 = new Button("发送");
    Button bon2 = new Button("关闭");
    Button bon3 = new Button("字体");
    //Font font = new Font("楷体",Font.PLAIN,15);
    Panel p = new Panel( );
   
    public static void main(String[] args) {
        new ChatClient( ).launchFrame( );//对象调用launchFrame( )方法
    }
    public ChatClient(){
        super("聊天程序");
    }
    public void launchFrame( ){//创建一个框架方法,它是一个自定义的方法
        this.setLocation(300,400);//this蔡卓宜为什么离的婚就是ChatClient类所创建的一个对象
        this.setSize(300,300);
        this.add(ta,BorderLayout.NORTH);//north要大写
        this.add(tf,BorderLayout.CENTER);
        bon1.an);
        bon2.an);
        bon3.an);
        p.add(bon1);
        p.add(bon2);
        p.add(bon3);
        p.an);
        this.add(p,BorderLayout.EAST);//面板也能当作一个组件
        this.pack( );//这句的作用是使上下的区域中间不出现一个不能写的区域
        ta.setEditable(false);
        ta.an);
        ta.setForeground(Color.BLUE);
        tf.an);
        tf.setForeground(Color.blue);
        this.addWindowListener(new WindowAdapter() {//需要导入event类,我们定义了一个
            public void windowClosing(WindowEvent e) {//匿名类来侦听关闭Frame这个事件源
                it(0);//然后来关闭框架的窗口
                disconnect();//这个方法必须在上一句的后面
            }
        });
        bon2.addActionListener(new   ActionListener(){ 
            public   void   actionPerformed(ActionEvent   evt){ 
            new   FrameD();   //调用FrameD类的一个构造方法
            } 
            }); 
        bon1.addActionListener(new tfListener( ));
        tf.addActionListener(new tfListener( ));//将成员类对象添加到事件侦听中去
        //bon3.addActionListener(new ffListener("字体框"));//如果这样直接调用,两个窗口将同时弹出
        bon3.addActionListener(new ActionListener(){//如果这样定义的话,它的效果是我们单击字体
            public void actionPerformed(ActionEvent e){//按钮的时候才会弹出一个字体对话框,它与
                new ffListener("字体框");//上面的那个不一样!!!
            }
        });
        this.setVisible(true);
        connect( );
        new Thread(new RecvThread()).start( );//线程的启动,这是用的第二种方法定义的线程
    }
     class   FrameD { 
         public JFrame f; 
         public   FrameD(){ 
        if(JOptionPane.showConfirmDialog(f,"您确定要退出吗?","提示",JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) 
         { 
        &it(0); 
         }
         } 
         } 
    private class tfListener implements ActionListener{//事件源是文本框,此处用的是一个成员类
        public void actionPerformed(ActionEvent e){
            //trim()方法的作用是当我们在文本框前几行先输入的是空格的时候是,它将省略空格,
            String str =&Text().trim();//还是以左对齐显示在文本域中
            ta.setText(str);//将从文本框里面发送过来的信息在文本域中显示出来
            tf.setText("");//清空文本框里面的内容
            try {
                dos.writeUTF(str);//服务器的send()方法中有这个方法
                dos.flush( );//在客户端向内存中写入数据的时候,必须将它全部输入到内存中,好方便服务器从内存中读取数据
            } catch (IOException e1) {
                    e1.printStackTrace();
            }//将数据从客户端写入内存中,中间可能出现传输错误,所以需要我们捕获异常
        }
    }
    private class RecvThread implements Runnable {

        public void run() {
            try {
            while(bConnected){
                String str;
                    str =&adUTF();
                    ta.setText("王强:"+str);
                }
            } catch (SocketException e){//这两个异常类必须写在IOException异常类的前面,以为他们是IOException的子类
                    System.out.println("退出了,bye!!!");
            } catch (EOFException e){
                    System.out.println("退出了,bye - bye!!!");
            } catch (IOException e) {
                    e.printStackTrace();
           
            }       
        }
           
    }
    class ffListener extends Frame implements ActionListener { 
        Choice font,size,bolder; 
        Button bb; 
        ffListener(String s) { 
            setTitle(s); 
            font=new Choice(); 
            bolder=new Choice(); 
            size=new Choice(); 
            Panel p1=new Panel(); 
            Panel p2=new Panel(); 
            bb=new Button("点击打开"); 
            bb.addActionListener(this); 
            p1.setLayout(new GridLayout(4,1)); 
            p2.setLayout(new GridLayout(4,1)); 
            GraphicsEnvironment LocalGraphicsEnvironment(); 
            String ss[]=gg.getAvailableFontFamilyNames(); 
            String bold[]={"Font.BOLD","Font.CENTER_BASELINE","Font.CENTER_BASELINE","Font.ITALIC", 
                    "Font.PLAIN","Font.ROMAN_BASELINE","Font.TRUETYPE_FONT"}; 
            for(int i=126;i<ss.length;i++) 
                font.add(ss[i]); 
            for(int i=12;i<=64;i+=2) { 
                String w=String.valueOf(i); 
                size.add(w); 
            } 
            for(int i=0;i<bold.length;i++) { 
                bolder.add(bold[i]); 
            } 
            p1.add(new Label("请选择字体")); 
            p1.add(font); 
            p1.add(new Label("请选择大小")); 
            p1.add(size); 
            p2.add(new Label("请选择字型")); 
            p2.add(bolder); 
            p2.add(new Label("请选择字体颜")); 
            p2.add(bb); 
            add(p2,BorderLayout.WEST); 
            add(p1,BorderLayout.EAST); 
            setSize(250,150); 
            setVisible(true); 
            pack(); 
            addWindowListener(new WindowAdapter() { 
工商银行信用卡办理
                public void windowClosing(WindowEvent ee) { 
                    it(0); 
                } 
            }); 
        } 
    public void actionPerformed(ActionEvent e) { 
            Color cc=JColorChooser.showDialog(this,"颜对话框",null); 
            bb.setBackground(cc);//应用举例 
        } 
        } 
       
    public void connect(){
        try {
            Socket s = new Socket("192.168.0.2",8888);//Socketutil类中
            dos = new OutputStream());
            dis = new InputStream());
            //System.out.println("Connect!!!");
            bConnected = true;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void disconnect(){
        try {
            dos.close();
            dis.close();
            s.close();
        } catch (IOException e) {
                e.printStackTrace();
        }
       
    }
}


************************************************************************************

import java.io.IOException;
import java.*;
import java.util.*;
import java.io.*;




public class ChatServer {
    boolean started = false;
    ServerSocket ss = null;
    //定义一个List接口的对象,用ArrayList类来实现,此种方法定义的是一个泛型,即我们所装入的对象只能是Client类型的东西,而不能再象以前
    List<Client> clients = new ArrayList<Client>( );//一样放在容器里面的对象全被封装为Object对象
    public static void main(String[] args) {
        new ChatServer( ).start( );
    }
    public void start( ){
        try {//因为数据在网络传输过程中可能会出现异常,所以我们要捕获
            ss = new ServerSocket(8888);//ServerSocket需要导入net
            started = true;
        } catch (BindException e){
            System.out.println("端口使用中..........");
            System.out.println("请关掉相关程序并重新运行服务器等不到天黑烟火不会太完美什么歌!!!");
            it(0);//关闭服务器的窗口
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
        while (started){
            while(true){
                //System.out.println("111111111");它起的作用是调试程序
                Socket s =ss.accept( );
                Client c = new Client(s);//生成可执行的线程
                System.out.println("A Client connnect!!!");
                new Thread(c).start();//然后启动线程
                clients.add(c);
                }
            }惠普电脑死机
        } catch(IOException e){
            e.printStackTrace();
        } 
        finally {
            try {
                ss.close();
            } catch(IOException e){
                e.printStackTrace();
            }
        }
    }
    class Client implements Runnable {//它是一个成员类,因为它定义在ChatServer类中
        private Socket s;
        private DataInputStream dis = null;//它与客户端不一样的是它的DataInputStream在前面
        private DataOutputStream dos = null;
        private boolean bConnected = false;
        public Client(Socket s){
            this.s = s;
            try {
            dis = new InputStream());
            dos = new OutputStream());
            bConnected = true;
        }catch (IOException e){
            e.printStackTrace();
        }
    }
        public void send(String str){
            try {
                dos.writeUTF(str);//只要一写writeUTF( ),我们就需要捕获异常
            } catch (IOException e) {
                ve(this);
                System.out.println("对方退出了!我从List容器里面删除的!!!");
                e.printStackTrace();
            }
           
        }
       
        public void run() {
            try {
                while(bConnected) {//客户端与服务器中的run( )方法的循环条件是一样的,都是bConnected
                    String str =&adUTF();//客户端与服务器中都是readUTF( )方法,我们在send( )方法中才有writeUTF()方法
                    System.out.println(str);
                    for (int i=0;i<clients.size();i++){
                        Client c =&(i);
                        c.send(str);
                        } 
                    }
                }catch (EOFException e) {
                    System.out.println("A Client closed!");
                }catch (IOException e) {
                    e.printStackTrace();
                }
                finally {
                    try {
                        if (dis!= null) {
                            dis.close( );
                        }
                        if (dos!= null){
                            dos.close();
                        }
                        if (s!= null){
                            s.close();
                        }
                   
                    } catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
               
        }
           
    }