无法在main之外成功创建JFrame类的实例

时间:2015-04-20 20:39:51

标签: java swing class jframe main

我正在编写一个简单的加密即时消息,它涉及两个项目:服务器和客户端。我让这两个工作得很好,但决定在客户端添加一个提示,要求提供服务器IP地址和端口号。在用户按下按钮后,我为其添加了一个动作侦听器,以创建即时消息类的实例,该实例扩展了JFrame。

当从这个动作监听器内部(或者在一个单独的方法中,我已经尝试过)完成此操作时,它会创建客户端JFrame,但内部不存在任何组件。客户端正常连接到服务器。

但是,在main方法中创建客户端时,程序正常工作。

以下是有效和无效的区别:

这不起作用:

okay.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            try{
                port = Integer.parseInt(portField.getText());
            }catch(NumberFormatException e){
                return;
            }
            serverIP = serverIPField.getText();
            dispose();
            Client c = new Client(serverIP, port);
            c.startRunning();
        }
    });

然而,这确实有效(同一类):

public static void main(String args[]){
    Client c = new Client(serverIP, port);
    c.startRunning();

}

我所做的一切,就是改变Client类的创建位置,从类构造函数(称为Prompt,它创建一个JFrame以请求IP和端口)到main方法。我尝试使用main方法从一个新类创建一个Client实例,它似乎工作正常。

正如我之前所说,JFrame已经创建并且打开正常,它甚至可以成功连接到服务器,但是没有任何组件存在(只是一个空白区域)。这很奇怪,因为在main方法中创建它时不是这种情况。

我不知道为什么会这样,所以如果有人能解释原因,那就太棒了。

感谢。

编辑:我感谢我可能没有添加足够的信息。这是Client构造函数:

public Client(String host, int port){
    super("Instant Messenger - Client");
    this.port = port;
    serverIP = host;
    initComponents();
    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation(dim.width/2-this.getSize().width/2, dim.height/2-this.getSize().height/2);
    setVisible(true);
    keys = new EncryptionKeys(1024);

}

开始运行方法:

public void startRunning(){

    try{
        connectToServer();
        setupStreams();
        exchangeKeys();
        whileChatting();
    }catch(EOFException eofEx){
        showMessage("\nClient Terminated connection");
    }catch(IOException ioEx){
        showMessage("\nCould not connect to server.");
    }finally{
        closeDown();
    }
}

由startRunning()调用的while聊天方法:

private void whileChatting() throws IOException{
    ableToType(true);
    do{
        try{
            message = (String) input.readObject();
            if(!keysSent){
                if(message.substring(0, 1).equals("n")){
                    try{
                    keys.nForeign = new BigInteger(message.substring(1, message.length()));
                    }catch(NumberFormatException nfEx){
                        showMessage("Error sending keys");
                    }
                }
                else if(message.substring(0, 1).equals("e")){
                    try{
                    keys.eForeign = new BigInteger(message.substring(1, message.length()));
                    keysSent = true;

                    }catch(NumberFormatException nfEx){
                        showMessage("Error sending keys");
                    }
                }
                continue;
            }
            showEncryptedMessage(message);
        }catch(ClassNotFoundException cnfEx){
            showMessage("\nUser Sending error");
        }
    }while(!message.equals("SERVER - END"));
}

dispose()关闭JFrame以提示用户。 Prompt类仅用于从用户那里获取有关IP地址和端口的信息,然后将其关闭,以便打开客户端。

1 个答案:

答案 0 :(得分:0)

管理Swing组件的所有代码(例如绘画,监听器等等)都发生在一个线程上:事件调度线程(EDT)。 startRunning方法调用whileChatting,它包含一个不立即退出的do / while循环。两种情景中会发生什么:

  1. 在main中创建客户端时,它将在主线程上创建。这允许while循环在Main线程上运行,允许EDT并行运行。 (注意:您应该使用SwingUtilities在EDT上创建GUI)
  2. 当在EDT上创建客户端时(在actionPerformed中),非终止循环将在EDT上发生,有效地锁定它并且不允许它执行任何任务直到它终止(换句话说,组件在在EDT免费之前,JFrame无法绘制,更新或做出反应)
  3. 如果您希望执行长时间运行的任务,则应考虑使用Thread