静态ObjectOutputStream引用在整个客户端代码中不起作用

时间:2013-11-28 21:09:28

标签: java javafx objectoutputstream

制作聊天应用程序,我最近将它从Swing移植到JavaFX。我遇到了使用ObjectOutputStream引用的问题。

在Client.java文件中,底部的toServer引用返回null。我认为使toServer static允许我访问代码中的任何位置的指针。只是无法弄清楚我做错了什么。

我收到了java.lang.NullPointerException     在Client.sendMessageToServer(Client.java:130) 我很感激任何意见,谢谢!

        Main.java
            import javafx.application.Application;
            import javafx.fxml.FXMLLoader;
            import javafx.scene.Scene;
            import javafx.scene.layout.AnchorPane;
            import javafx.scene.layout.BorderPane;
            import javafx.stage.Stage;

            import java.io.IOException;

            /**
             * @author Sergey
             *         Date: 11/22/13 Time: 9:10 PM
             */
            public class Main extends Application
            {
                private Stage      primaryStage;
                private BorderPane rootLayout;


                /**
                 * this code creates a borderpane with a menubar at the top, the purpose is of
                 * this is to nest the chat client into the borderpane's centre location
                 */
                @Override
                public void start( Stage primaryStage )
                {
                    this.primaryStage = primaryStage;
                    this.primaryStage.setTitle( "chatninjas client" );

                    try
                    {
                        // load the menubar layout from the fxml file
                        FXMLLoader loader = new FXMLLoader( Client.class.getResource( "ninjamenu.fxml" ) );
                        rootLayout = ( BorderPane ) loader.load();
                        Scene scene = new Scene( rootLayout );
                        primaryStage.setScene( scene );
                        primaryStage.show();
                    }
                    catch( Exception ex )
                    {
                        // Exception gets thrown if the fxml file could not be loaded
                        ex.printStackTrace();
                    }

                    showChatRoom();
                }


                /**
                 * Shows the chat room area that will be nested into the centre of the borderpane above
                 */
                public void showChatRoom()
                {
                    try
                    {
                        // Load the fxml file and set into the center of the main layout
                        FXMLLoader loader = new FXMLLoader( Client.class.getResource( "ninja.fxml" ) );
                        AnchorPane overviewPage = ( AnchorPane ) loader.load();
                        rootLayout.setCenter( overviewPage );
                    }
                    catch( IOException e )
                    {
                        // Exception gets thrown if the fxml file could not be loaded
                        e.printStackTrace();
                    }
                }

                /**
                 * Returns the main stage.
                 *
                 * @return
                 */
                public Stage getPrimaryStage()
                {
                    return primaryStage;
                }

                public static void main( String[] args )
                {
                    launch( args );
                }
            }


        NinjaController.java
            import javafx.event.ActionEvent;
            import javafx.event.EventHandler;
            import javafx.fxml.FXML;
            import javafx.fxml.Initializable;
            import javafx.scene.control.Button;
            import javafx.scene.control.TextArea;
            import javafx.scene.control.TextField;

            import java.net.URL;
            import java.util.ResourceBundle;

            public class NinjaController implements Initializable
            {
                @FXML //  fx:id="userOutput"
                static protected TextArea  userOutput = null;

                @FXML //  fx:id="userInput"
                static protected TextField userInput  = null;

                @FXML //  fx:id="sendButton"
                static protected Button    sendButton = null;

                @FXML
                ResourceBundle resources = null;

                @FXML
                URL location = null;

                @Override
                public void initialize( URL fxmlFileLocation, ResourceBundle resources )
                {
                    this.resources = resources;
                    this.location  = fxmlFileLocation;

                    System.out.println( "about to show the resources var: "        + resources );
                    System.out.println( "about to show the fxmlFileLocation var: " + fxmlFileLocation );

                    userInput.setOnAction( new EventHandler<ActionEvent>()
                    {
                        @Override
                        public void handle( javafx.event.ActionEvent actionEvent )
                        {
                            Client.sendMessageToServer( constructMessageFromFXMLuserInput() );
                            userInput.setText( "" );

                            System.out.println( "send via enter key" );

                        }
                    });

                    sendButton.setOnAction( new EventHandler<javafx.event.ActionEvent>()
                    {
                        @Override
                        public void handle( javafx.event.ActionEvent actionEvent )
                        {
                            Client.sendMessageToServer( constructMessageFromFXMLuserInput() );
                            userInput.setText( "" );

                            System.out.println( "sent via send button" );
                        }
                    } );
                }

                /* dont think i need this anymore
                public void onEnter()
                {
                    System.out.println( "user hit enter while mouse was focused in the textfield with this message: " + userInput.getText() );
                }
                */

                // returns a String trimmed of spaces
                public static String retrieveTextFromFXMLuserInput()
                {
                    return userInput.getText().trim();
                }

                // appends the incoming text area (userOut) with an inbound message
                public static void sendMessageToFXMLuserOutput( Message incomingMessage )
                {
                    userOutput.appendText( incomingMessage.getMsgBody() + "\n" );
                }

                public static Message constructMessageFromFXMLuserInput()
                {
                    // if the userInput field is empty, don't even bother sending the message
                    if( retrieveTextFromFXMLuserInput().equals( "" ))
                    {
                        System.out.println( "message is empty, didnt send anything" );
                        return null;
                    }

                    return new Message( retrieveTextFromFXMLuserInput(),
                                        null,    // font entry
                                        null,    // font entry
                                        "bob" /*getUserName()*/ );
                }
            }

        Client.java:

            import java.io.IOException;
            import java.io.ObjectInputStream;
            import java.io.ObjectOutputStream;
            import java.net.Socket;
            import java.util.Date;

            import static java.text.DateFormat.MEDIUM;
            import static java.text.DateFormat.getTimeInstance;

            public class Client
            {
                /*
                    These are the user set preferences, the userName will be set by the user
                    when the Client loads.
                */
                private static String userName;  // this field will be changed when user is prompted for a name
                private static int fontSize = 12;


                // Object IO streams
                private static ObjectOutputStream toServer;
                private ObjectInputStream  fromServer;

                /*
                Plan to update the port selection to use a showInputDialog that will request a user
                specified port and url of the server to connect to.
                Like the other showInputDialogs, this will have a server address and port preset.
                 */
                private static final int port = 4000;

                String  date;
                boolean connected;

                // static Font myFont = new Font( fontType, Font.BOLD, fontSize ); // testing the font functionality // works!

                Message wantToSend;

                public Client() throws IOException
                {
                    String hostname = "localhost";

                    Socket socket = new Socket( hostname, port );

                    // prompt the user for an alias using JOptionPane.showInputDialog
                    userName = "bob"; //getName(); // getName needs to be rewritten, it used the old JFrames approach, needs to use the new css approach

                    toServer   = new ObjectOutputStream( socket.getOutputStream() );
                    fromServer = new ObjectInputStream(  socket.getInputStream() );

                    // send the username to the server for "online list"
                    // ** feature is beta right now **
                    wantToSend = new Message( userName );
                    toServer.writeObject( wantToSend );

                    Message receiveMessage;

                    connected = true;

                    while( connected )
                    {
                        try
                        {
                            // make the date look pretty: 8:54:17 PM
                            date = getTimeInstance( MEDIUM ).format( new Date() );

                            receiveMessage = ( Message ) fromServer.readObject();

                            if( receiveMessage != null )
                            {
                                sendMessageToController( receiveMessage );
                            }
                            else
                            {
                                sendMessageToController( new Message( 1, ">>>  Message from server == null <<< BUGCODE1001" ) );
                            }
                        }
                        catch( ClassNotFoundException e1 )
                        {
                            e1.printStackTrace();
                        }
                    }
                }

                /*                   _     _                                                   _     _
                                    | |   | |                           ___                   | |   | |
                       __ _    ___  | |_  | |_    ___   _ __   ___     ( _ )      ___    ___  | |_  | |_    ___   _ __   ___
                      / _` |  / _ \ | __| | __|  / _ \ | '__| / __|    / _ \/\   / __|  / _ \ | __| | __|  / _ \ | '__| / __|
                     | (_| | |  __/ | |_  | |_  |  __/ | |    \__ \   | (_>  <   \__ \ |  __/ | |_  | |_  |  __/ | |    \__ \
                      \__, |  \___|  \__|  \__|  \___| |_|    |___/    \___/\/   |___/  \___|  \__|  \__|  \___| |_|    |___/
                       __/ |
                      |___/
                */

                /**
                 * Prompt for and return the desired screen name.
                 */


                // need to update this code with nicole's login screen functionality
                /*
                public String getName()
                {
                    // the random generator is for testing purposes, i didn't want to keep having
                    // to type in usernames to test features
                    return ( String ) JOptionPane.showInputDialog(
                            null,
                            "Choose a name:",
                            "Screen name selection",
                            JOptionPane.PLAIN_MESSAGE,
                            null,
                            null,
                            "moose" + ( int ) ( Math.random() * ( 9999 - 1111 ) ) );
                }
                */

                public void sendMessageToController( Message sendThisToController )
                {
                    System.out.println("--sending message to controller");
                    NinjaController.sendMessageToFXMLuserOutput( sendThisToController );
                    System.out.println("--message sent to controller");
                }

                static void sendMessageToServer( Message messageToSend )
                {
                    try
                    {
                        if( ! ( messageToSend.getMsgBody().isEmpty() ) )
                        {
                            // sends wantToSend object to the  server via ObjectOutputStream->OutputStream->Socket
                            toServer.writeObject( messageToSend ); // exception:  java.lang.NullPointerException
//at Client.sendMessageToServer(Client.java:130)
                            print( "message sent to server" );
                            toServer.flush();
                        }
                        else if( messageToSend == null ) // this shouldn't ever happen  BUGCODE1000
                        {
                            print( " >>> wantToSend is null .. this message is a bug  BUGCODE1000 <<< " );
                        }
                        else;
                    }
                    catch( IOException ex )
                    {
                        System.err.println( ex );
                    }

                }

                // basic stdout print because System.out.println( "" )
                public static void print( String printThisMessageToSystemOutPrintln )
                {
                    System.out.println( printThisMessageToSystemOutPrintln );
                }
            }

编辑: 好的,我发现了我的问题。

我的客户端没有与我的服务器进行通信,我遇到了运行Controller或Client类的情况,并且无法弄清楚程序为什么会冻结。

所以我在Client上实现了Runnable,并让Controller创建了一个新线程:         客户端任务= new Client();         新线程(任务).start();

现在一切都很时髦。

0 个答案:

没有答案