2014-12-26 2 views
0

Я написал этот простой многопоточный чат, и я пытаюсь отправить вывод клиент/сервер в графический интерфейс, чтобы отобразить его в текстовой области в чате, но я получаю исключение из нулевого указателя в следующей строке:вопрос при отправке вывода сокета в GUI

output.write(line + "\n"); 

вот полный код для GUI: код

import java.awt.*; 
import javax.swing.*; 
import javax.swing.JTextField; 
import javax.swing.JFrame; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.io.IOException; 
import javax.swing.JButton; 
import java.io.Writer; 


public class GUI { 

    private JFrame frame; 
    private JButton btnSend, btnConnect; 
    private JTextArea txtChat; 
    private JTextField fldText, fldName; 
    private JList clientList; 
    private DefaultListModel listModel; 
    private JScrollPane sc, scClients; 
    private JPanel jpS2All, jpS2Client, jpS2Text; 
    private String Name; 
    private JLabel lblErr; 
    private Writer output; 

    public GUI(String Name, Writer output) { 
     this.Name = Name; 
     this.output = output; 
    } 

    public GUI() { 

    } 


    class handler implements ActionListener, MouseListener { 

     handler(String Name) { 

     } 

     handler() { 

     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 


      clients();     //it seems this line made the error because it creates the 
      listModel.addElement(Name);//gui and sends the output to textSend actionlistener 
             //to display it in gui 
             //while the output is empty, right? 
             //is there any way to handle this? 

     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
      fldName.setText(""); 
     } 

     @Override 
     public void mousePressed(MouseEvent e) { 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
     } 

     @Override 
     public void mouseEntered(MouseEvent e) { 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
     } 

    } //end of handler 

    class textSend implements ActionListener { 

     textSend(String Name, Writer output) { 

     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      String line = fldText.getText(); 
      try { 
       output.write(line + "\n");    // the null exception error shows the 
       output.flush();      // error source at this line! 
      } catch (IOException ioe) { 
       txtChat.append("Other party hung up!"); 
      } 
      String contenet = Name + ":" + output; 
      txtChat.append(contenet); 
      fldText.setText(""); 
     } 

    }//end of textSend 

    public void creatServer() { 

     frame = new JFrame("enter"); 
     frame.setBounds(50, 50, 300, 200); 
     btnConnect = new JButton("connect"); 
     lblErr = new JLabel(); 
     lblErr.setText(""); 
     frame.add(btnConnect, BorderLayout.EAST); 
     fldName = new JTextField(); 
     fldName.setText("enter your name"); 
     fldName.addMouseListener(new handler()); 

     btnConnect.addActionListener(new handler(getName())); 

     frame.add(fldName, BorderLayout.CENTER); 
     frame.setVisible(true); 

    } 


    public void clients() { //to create the chatroom GUI 
     frame = new JFrame("friends"); 
     frame.setBounds(100, 100, 400, 400); 
     jpS2All = new JPanel(); 
     txtChat = new JTextArea(); 
     txtChat.setRows(25); 
     txtChat.setColumns(25); 
     txtChat.setEditable(false); 

     sc = new JScrollPane(txtChat); 
     jpS2All.add(sc); 
     frame.add(jpS2All, BorderLayout.WEST); 
     jpS2Text = new JPanel(); 

     //////////////////////// 
     fldText = new JTextField(); 
     fldText.setColumns(34); 
     fldText.setHorizontalAlignment(JTextField.RIGHT); 
     fldText.addActionListener(new textSend(getName(), output)); 
     jpS2Text.add(fldText); 
     frame.add(jpS2Text, BorderLayout.SOUTH); 

     ///////// 
     jpS2Client = new JPanel(); 

     listModel = new DefaultListModel(); 
     clientList = new JList(listModel); 
     clientList.setFixedCellHeight(14); 
     clientList.setFixedCellWidth(100); 
     scClients = new JScrollPane(clientList); 

     frame.add(jpS2Client.add(scClients), BorderLayout.EAST); 
     ///////// 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     frame.pack(); 

    }//end of clients 

    public String getName() { 
     Name = fldName.getText(); 
     return Name; 
    } 

    public void appendText(final String message) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       txtChat.append(message); 
      } 
     }); 
    } 
} 

сервер:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.Writer; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class server { 

    public void start() throws IOException { 
     ServerSocket serverSocket = new ServerSocket(1234); 
     while (true) { 
      Socket socket = serverSocket.accept(); 
      ClientThread t = new ClientThread(socket); 
      t.start(); 
     } 
    } 

    public static void main(String[] args) throws IOException { 
     server server = new server(); 
     server.start(); 

    } 

    class ClientThread extends Thread { 

     Socket socket; 
     InputStream sInput; 
     OutputStream sOutput; 
     GUI gui = new GUI(); 
     String Name; 

     ClientThread(Socket socket) { 
      this.socket = socket; 

     } 

     @Override 
     public void run() { 
      try { 
       BufferedReader sInput 
         = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
       Writer sOutput = new OutputStreamWriter(socket.getOutputStream()); 
       Name = gui.getName(); 
       gui = new GUI(Name, sOutput); 

       try { 
        String line; 
        while ((line = sInput.readLine()) != null) { 
         gui.appendText(line); 
        } 
       } catch (IOException ex) { 
        Logger.getLogger(client.class.getName()).log(Level.SEVERE, null, ex); 
       } 

      } catch (IOException e) { 
      } 
     } 
    } 
} 

кл диентом сторона:

import java.net.*; 
import java.io.*; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class client { 

    private Socket s; 
    private String Name; 
    private GUI gui; 
    private Writer output; 
    private BufferedReader input; 

    public void start() { 

     try { 
      s = new Socket("127.0.0.1", 1234); 
     } catch (IOException ex) { 

     } 
     try { 
      input = new BufferedReader(new InputStreamReader(s.getInputStream())); 
      output = new OutputStreamWriter(s.getOutputStream()); 
     } catch (IOException eIO) { 

     } 
     Name = gui.getName(); 
     new GUI(Name, output); 
     new ListenFromServer().start(); 

    } 

    public static void main(String[] args) { 
     client cl = new client(); 
     GUI gui = new GUI(); 
     gui.creatServer(); 
    } 

    class ListenFromServer extends Thread { 

     public void run() { 
      try { 
       String line; 
       while ((line = input.readLine()) != null) { 
        gui.appendText(line); 
       } 
      } catch (IOException ex) { 
       Logger.getLogger(client.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 

    } 

} 

Я знаю, что мой вопрос немного громоздким, но я очень ценю, чтобы помочь мне справиться с этой проблемой!

+0

В вашем конструкторе по умолчанию 'GUI gui = new GUI();' вы никогда не инициализируете 'output' и поэтому всегда' null' – chancea

+0

http://stackoverflow.com/questions/218384/what-is -a-null-pointer-exception-and-how-do-i-fix-it – markspace

+0

также рассматривают использование классов 'Anonymous' для определения ваших слушателей действий ... он сокращает много кода – chancea

ответ

1

сообщение об ошибке показывает, что одна из переменных, используемых в выражении, была нулевой. Это может быть либо output, либо line.

Как уже упоминалось, вы вызываете конструктор GUI() без аргументов, поэтому поле output не инициализируется. Вы должны удалить конструктор без аргументов, если у вас нет возможности инициализировать поле output и оставить его только с аргументами.

+0

да, спасибо за помощь – Masoud

2

Я смотрю на ваш код, и это очевидно, что output является null при попытке output.write(line + "\n"); Поэтому я пошел и посмотрел на возможный путь исполнения, которые могли бы оставить output ООН инициализирован. Здесь отладка очень удобна.

Вот ваш путь исполнения:

В вашей основной метод client вы создаете новый GUI, а затем вызвать gui.creatServer();

public static void main(String[] args) { 
    client cl = new client(); 
    GUI gui = new GUI(); 
    gui.creatServer(); 
} 

выход не был назначен и по-прежнему нулевой

в методе creatServer(); у вас есть эта строка:

fldName.addMouseListener(new handler()); 

которой actionPerformed метод handler вызывает clients(); метод, который имеет следующую строку:

fldText.addActionListener(new textSend(getName(), output)); 

примечание output является еще нулевой

(теперь ваш textSend класс не даже делать ничего внутри конструктор, но в стороне, даже если это произошло, вы все еще используете переменную output от класса GUI)

у вас есть метод actionPerformed в textSend класса, который имеет следующую строку:

output.write(line + "\n"); 

никогда не инициализируется output это еще нуль, что дает вам NullPointer

Пожалуйста, смотрите What is a NullPointerException, and how do I fix it? как @markspace связанного в комментариях. Кроме того, вы должны научиться отлаживать небольшие программы.

Смотрите следующие ссылки:

http://ericlippert.com/2014/03/05/how-to-debug-small-programs/ http://blogs.msdn.com/b/smallbasic/archive/2012/10/09/how-to-debug-small-basic-programs.aspx

Опять кроме того, рассмотреть возможность использования Anonymous классов, чтобы облегчить на этих строк кода, что также делает код более удобным для отладки и более удобным для чтения.

Последняя мысль, не забудьте использовать стандарт Naming Conventions для используемого вами языка. ваш код в настоящее время имеет много неправильных строчных классов и некоторые прописные методы/свойства.

+0

да, вы правы, думаю, я должен узнать больше! – Masoud

+0

@Masoud Даже эксперты всегда учатся больше :) – chancea

+0

да :) спасибо большое @chancea – Masoud

Смежные вопросы