2

tcpソケットで行をリッスンして送信し、受信した情報をに追加する小さなプログラムを作成しましたJTextArea。これを使用して、ゲームを開かずにMinecraftサーバーでチャットします。

昨夜は元気に働いていましたが、起きたときはうまくいきませんでした。NetBeansを開いて実行すると、次のエラーが発生しました。

Exception in thread "main" java.lang.NullPointerException
    at com.xxx.mcchat.chat.main(chat.java:333)

誰かが何が悪いのか説明できますか?

コードは次のとおりです(http://pastebin.com/FPNty0qf):

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.xxx.mcchat;

import java.io.*;
import java.net.*;
import net.sf.json.*;
import org.apache.commons.beanutils.*;
import org.apache.commons.collections.*;
import org.apache.commons.lang.*;
import net.sf.ezmorph.*;
import org.apache.commons.logging.*;
import java.awt.event.*;
import javax.swing.UIManager;
/**
 *
 * @author xxx
 */
public class chat extends javax.swing.JFrame {

    /**
     * Creates new form chat
     */

    public chat() {
        initComponents();
    }

    public void send(String user, String message){
        Socket socket = null;
        PrintWriter out = null;
        BufferedReader in = null;


        try {
            socket = new Socket("mc.xxx.net", 20060);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection");
            System.exit(1);
        }

        BufferedReader read = new BufferedReader(new InputStreamReader(System.in));

                //System.out.println(in.readLine()); //Uncomment to debug
        if(username != null){
            out.println("/api/call?method=broadcast&args="+"[\"§7[Web] §b"+username+"§7:§f "+message+"\"]"+"&key=f0e2ad47a9a43c783d2c54f396f655c9279829c8c69ae9f52934648098dec993");
            chatArea.append(username + ": " + message + "\n\r");
            if(autoscrollCheck.isSelected()){
                chatArea.setCaretPosition(chatArea.getText().length() - 1);
            }
        }else{
            chatArea.append("You must set your username!!" + "\n\r");
            if(autoscrollCheck.isSelected()){
                chatArea.setCaretPosition(chatArea.getText().length() - 1);
            }

        }
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                       
    private void initComponents() {

        jCheckBoxMenuItem1 = new javax.swing.JCheckBoxMenuItem();
        jToggleButton1 = new javax.swing.JToggleButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        chatArea = new javax.swing.JTextArea();
        input = new javax.swing.JTextField();
        send = new javax.swing.JButton();
        user = new javax.swing.JTextField();
        userset = new javax.swing.JButton();
        autoscrollCheck = new javax.swing.JCheckBox();
        jLabel1 = new javax.swing.JLabel();

        jCheckBoxMenuItem1.setSelected(true);
        jCheckBoxMenuItem1.setText("jCheckBoxMenuItem1");

        jToggleButton1.setText("jToggleButton1");

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Minecraft Chat");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowOpened(java.awt.event.WindowEvent evt) {
                formWindowOpened(evt);
            }
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        chatArea.setEditable(false);
        chatArea.setBackground(new java.awt.Color(0, 0, 0));
        chatArea.setColumns(20);
        chatArea.setFont(new java.awt.Font("Consolas", 0, 14)); // NOI18N
        chatArea.setForeground(new java.awt.Color(255, 255, 255));
        chatArea.setLineWrap(true);
        chatArea.setRows(5);
        jScrollPane1.setViewportView(chatArea);

        input.setToolTipText("Enter message here");
        input.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                inputKeyPressed(evt);
            }
        });

        send.setText("Send");
        send.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendActionPerformed(evt);
            }
        });

        user.setToolTipText("");
        user.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                userActionPerformed(evt);
            }
        });
        user.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                userKeyPressed(evt);
            }
        });

        userset.setText("Set");
        userset.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                usersetActionPerformed(evt);
            }
        });

        autoscrollCheck.setSelected(true);
        autoscrollCheck.setText("Auto Scroll");
        autoscrollCheck.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                autoscrollCheckActionPerformed(evt);
            }
        });

        jLabel1.setText("Enter Username:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(user, javax.swing.GroupLayout.PREFERRED_SIZE, 218, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(userset)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(autoscrollCheck))
                    .addComponent(jScrollPane1)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(input, javax.swing.GroupLayout.PREFERRED_SIZE, 649, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(send)))
                .addGap(10, 10, 10))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(11, 11, 11)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(1, 1, 1)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(user, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel1)))
                    .addComponent(userset)
                    .addComponent(autoscrollCheck))
                .addGap(6, 6, 6)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE)
                .addGap(6, 6, 6)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(1, 1, 1)
                        .addComponent(input, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(send))
                .addGap(11, 11, 11))
        );

        pack();
    }// </editor-fold>                      

    String username = null;
    private void inputKeyPressed(java.awt.event.KeyEvent evt) {                              
           int key = evt.getKeyCode();
           if (key == KeyEvent.VK_ENTER) {  
                send(username, input.getText());
                input.setText("");
              }
    }                               

    private void sendActionPerformed(java.awt.event.ActionEvent evt) {                                   
        send(username, input.getText());
        input.setText("");
    }                                   

    private void usersetActionPerformed(java.awt.event.ActionEvent evt) {                                       
        if(username == null){
                    if(!"".equals(user.getText())){
                        username = user.getText();
                        chatArea.append("Username set!"+"\n\r");
                        if(autoscrollCheck.isSelected()){
                            chatArea.setCaretPosition(chatArea.getText().length() - 1);
                        }
                    }else{
                        chatArea.append("Username can not be blank."+"\n\r");
                        if(autoscrollCheck.isSelected()){
                            chatArea.setCaretPosition(chatArea.getText().length() - 1);
                        }
                    }
                }else{
                    send(username, "§7changed name to " + user.getText());
                    username = user.getText();
                }
    }                                      

    private void userActionPerformed(java.awt.event.ActionEvent evt) {                                   
        // TODO add your handling code here:
    }                                   

    private void userKeyPressed(java.awt.event.KeyEvent evt) {                              
           int key = evt.getKeyCode();
           if (key == KeyEvent.VK_ENTER) {  
                if(username == null){
                    if(!"".equals(user.getText())){
                        username = user.getText();
                        chatArea.append("Username set!"+"\n\r");
                        if(autoscrollCheck.isSelected()){
                            chatArea.setCaretPosition(chatArea.getText().length() - 1);
                        }
                    }else{
                        chatArea.append("Username can not be blank."+"\n\r");
                        if(autoscrollCheck.isSelected()){
                            chatArea.setCaretPosition(chatArea.getText().length() - 1);
                        }
                    }
                }else{
                    send(username, "§7changed name to " + user.getText());
                    username = user.getText();
                }
              }
    }                              

    private void formWindowClosing(java.awt.event.WindowEvent evt) {                                   

    }                                 

    private void formWindowOpened(java.awt.event.WindowEvent evt) {                               
        // TODO add your handling code here:
    }                                

    private void autoscrollCheckActionPerformed(java.awt.event.ActionEvent evt) {                                               
        // TODO add your handling code here:
    }                                              

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) throws IOException {

        /* Set the system look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            javax.swing.UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(chat.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(chat.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(chat.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(chat.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new chat().setVisible(true);
            }
        });
        Socket socket = null;
        PrintWriter out = null;
        BufferedReader in = null;


        try {
            socket = new Socket("mc.xxx.net", 20060);
            out = new PrintWriter(socket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection");
            System.exit(1);
        }

        BufferedReader read = new BufferedReader(new InputStreamReader(System.in));

                //System.out.println(in.readLine()); //Uncomment to debug

        out.println("/api/subscribe?source=chat&key=1e287587f5d1d45255f4708467eeaf8a71085f9ccfd8a354523d233cf5a77be4&show_previous=true");
        out.println("/api/subscribe?source=connections&key=e410592b70c0288654e6c1040edb0f21811dcb3f2ee11051163f36be9be00788&show_previous=false");

        while(true){
            String jsonString = in.readLine();
            JSONObject obj = JSONObject.fromObject(jsonString); 
            JSONObject success = obj.getJSONObject("success");
            if(success.get("message") != null){
                chatArea.append("<" + success.get("player") + "> " + success.get("message") + "\n\r");
                if(autoscrollCheck.isSelected()){
                    chatArea.setCaretPosition(chatArea.getText().length() - 1);
                }
            }else if (success.get("action") != null){
                chatArea.append(success.get("player") + " " + success.get("action") + "\n\r");
                if(autoscrollCheck.isSelected()){
                    chatArea.setCaretPosition(chatArea.getText().length() - 1);
                }
            }
        }
    }

    // Variables declaration - do not modify                     
    public static javax.swing.JCheckBox autoscrollCheck;
    public static javax.swing.JTextArea chatArea;
    private javax.swing.JTextField input;
    private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToggleButton jToggleButton1;
    private javax.swing.JButton send;
    private javax.swing.JTextField user;
    private javax.swing.JButton userset;
    // End of variables declaration                


}

(PS GUIジェネレーターを使用しているので不機嫌にならないでください。これは私の最初のプログラムです。手​​作業でそれを行うことを学ぶことを約束します)

4

3 に答える 3

3

null行333にあることができる唯一のものはですchatArea。(もしそうならsuccessnull332行目のifステートメントで例外がスローされます。)他の人が示唆しているように、333行目に到達する前に初期化されていない競合状態がある可能性があります。

これを修正する正しい方法は、次chatAreaの呼び出しで呼び出しを囲むことSwingUtilities.invokeLaterです。

final JSONObject success = obj.getJSONObject("success");
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        if (success.get("message") != null) {
            chatArea.append("<" + success.get("player") + "> " + success.get("message") + "\n\r");
            if (autoscrollCheck.isSelected()) {
                chatArea.setCaretPosition(chatArea.getText().length() - 1);
            }
        } else if (success.get("action") != null) {
            chatArea.append(success.get("player") + " " + success.get("action") + "\n\r");
            if (autoscrollCheck.isSelected()) {
                chatArea.setCaretPosition(chatArea.getText().length() - 1);
            }
        }
    }
});

Swingコンポーネントに変更を加えるときはいつでも、イベントディスパッチスレッドで呼び出す必要があります。さらに、EDTはシングルスレッドのキューベースのエグゼキュータであるため、以前に送信したランナブルが完了するまで待機することが保証されているため、chatArea確実に設定されます。

もう1つの注意:一般的UIManagerに、invokeLater呼び出しを呼び出しでラップすることもお勧めします。

編集:私はあなたが常に電話で何をラップすべきかについてもう少し明確にしたいと思いinvokeLaterます:

  • Swingコンポーネントの構築
  • Swingコンポーネントのプロパティの変更
  • Swingコンポーネントのデータモデルを変更する(必ずしもデータを取得する必要はなく、イベントの発生など、変更されたことを気にするコンポーネントにEDTで発生する必要があることを伝えるだけです)
  • UIManagerルックアンドフィールの設定やキーの値の変更など、プロパティの変更
  • ルックアンドフィールのインスタンス化
  • のサブクラスのインスタンス化ComponentUI
  • コンテナへのコンポーネントの追加とコンテナからのコンポーネントの削除

ラップする必要がないもの:

  • まだ表示されていないコンポーネントのプロパティの変更コメントのRobinによると、これはEDTで引き続き行う必要があります。
  • への呼び出しrepaint
  • に電話するvalidate、またはinvalidate(私はこれについて確認を見つける必要があると思います)

これをすべて行うと、新しいルックアンドフィールに切り替えるときはいつでも、EDTで呼び出されないものに問題はありません。

簡単に言うと、Swingはスレッドセーフではないため、常にイベントディスパッチスレッドからSwingコンポーネントメソッドを呼び出す必要があります。

また、私が忘れているかもしれないことについての私のリストのための提案を歓迎します。

Swingでのスレッド化について説明しているリソースは次のとおりです。

于 2012-11-10T00:25:02.430 に答える
2

static問題は、データと非データを簡単に切り替えられることですstatic。最初に、プログラムが実行されますmain()static)。その中で、あなたは参照しますchatArea(333行目もstatic)。ただし、コンストラクター(non-)で発生する(non- )の呼び出し時にのみ設定さchatAreaます。これは、関数の残りの部分の前に常に呼び出されるとは限りません。initComponents()staticstatic

方法論に基づいて、invokeLaterに続くチャットプログラムに関連するすべてのものをコンストラクター(またはそうでないメソッド)に移動する必要があります。 invokeLater static

基本的に、あるべき唯一のものstaticはあなたのmain()方法です。残りはすべきではありませんstatic。それが役立つ場合は、参照元の新しいクラスに物事を分けますmain()。これは、プログラムを初期化してから、チャット関連のすべて実行するのに役立ちます。

于 2012-11-10T00:16:21.337 に答える
1

それはおそらくそれを時々機能させる競合状態です。メインスレッドが行333に到達するまでに変数が初期化されることは保証されていません。これは、その前にいくつかの行chatAreaを介してGUIの初期化が延期されたためです。invokeLater()

java.awt.EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        new chat().setVisible(true);
    }
});

これらのスレッド間で同期が必要です。または、これも機能するはずですが、メインスレッドでGUIを初期化するだけです。

final chat chatObject = new chat();
java.awt.EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        chatObject.setVisible(true);
    }
});
于 2012-11-10T00:13:18.440 に答える