0

我对java很陌生,如果您能帮助我解决以下问题,我将不胜感激。

我有一个连接到 ftp 服务器的应用程序。当它连接时,我想显示从服务器接收到的每条消息到 jtextpane。

我遇到的问题是,当我单击连接按钮时,应用程序冻结并且立即显示整个消息。我试过 swingutilies.invokelater,但它不起作用。请参阅下面的代码。

btnConnect.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                // TODO Auto-generated method stub

                try {

                    if(validation())
                    {

                        ftpServer = new FTPServer(txtusername.getText(), txtPassword.getText());
                        ftpServer.connectServer(txtSysMsg);

                    }



                } catch (BadLocationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


            }
        });


import java.io.IOException;

import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyledDocument;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

public class FTPServer
{
    String username;
    String password;
    FTPClient ftpClient;

    String error;
    String errorType;

    DisplayMessage displayMessage = new DisplayMessage();

    FTPTandem(String user, String pass)
    {

        username = user;
        password = pass;

    }


    public void connectServer(JTextPane txtSys) throws BadLocationException
    {

        ftpClient = new FTPClient();
        try
        {

            ftpClient.connect("xxx.xxx.xxx.xxx", 21);
            displayMessage.writeDoc(txtSys, "Connecting to xxx.xxx.xxx.xxx" +":"+ftpClient.getRemotePort()+")", "status");


            if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode()))
            {
                displayMessage.writeDoc(txtSys, "Connection established, waiting for welcome message...", "status");
                displayMessage.writeDoc(txtSys, ftpClient.getReplyString(), "response");
                displayMessage.writeDoc(txtSys, "USER "+username, "command");
                displayMessage.writeDoc(txtSys, "PASS "+password.replaceAll("[\\w\\W]", "*"), "command");

                if(ftpClient.login(username, password))
                {
                    displayMessage.writeDoc(txtSys, ftpClient.getReplyString(), "response");
                    displayMessage.writeDoc(txtSys, "SYST", "command");
                    displayMessage.writeDoc(txtSys,ftpClient.getSystemType(),"response");
                    displayMessage.writeDoc(txtSys,"PASV","command");
                    ftpClient.enterRemotePassiveMode();
                    displayMessage.writeDoc(txtSys,ftpClient.getReplyString(),"response");


                    ftpClient.logout();
                    ftpClient.disconnect();

                }
                else
                {
                    displayMessage.writeDoc(txtSys, ftpClient.getReplyString(), "error");
                    ftpClient.logout();
                    ftpClient.disconnect();

                }

            }
            else
            {
                ftpClient.disconnect();
                displayMessage.writeDoc(txtSys, "FTP server connection refused", "error");

            }



        } 
        catch (IOException e) 
        {
            if(ftpClient.isConnected())
            {
                try 
                {
                    ftpClient.logout();
                    ftpClient.disconnect();

                } 
                catch (IOException e1) 
                {

                }

            }

            displayMessage.writeDoc(txtSys, "Cannot connect", "error");

        }

    }




}

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;


public class DisplayMessage
{

    public SimpleAttributeSet styleDisplay(String type)
    {
        SimpleAttributeSet style = new SimpleAttributeSet();

        if (type.equalsIgnoreCase("error"))
        {
            StyleConstants.setForeground(style, Color.RED); 
            StyleConstants.setFontSize(style, 14);
            StyleConstants.setFontFamily(style, "Cambria");
            StyleConstants.setBold(style, false);

        }
        else if (type.equalsIgnoreCase("response"))
        {
            StyleConstants.setForeground(style, new Color(0,90,0) );
            StyleConstants.setFontSize(style, 14);
            StyleConstants.setFontFamily(style, "Cambria");
            StyleConstants.setBold(style, false);
        }
        else if (type.equalsIgnoreCase("status"))
        {
            StyleConstants.setForeground(style, Color.BLACK);   
            StyleConstants.setFontSize(style, 14);
            StyleConstants.setFontFamily(style, "Cambria");
            StyleConstants.setBold(style, false);
        }
        else if (type.equalsIgnoreCase("command"))
        {
            StyleConstants.setForeground(style, Color.blue);    
            StyleConstants.setFontSize(style, 14);
            StyleConstants.setFontFamily(style, "Cambria");
            StyleConstants.setBold(style, false);
        }

        return style;
    }

    public String messagePrefix(String meg, String type)
    {
        String reply = new String();

        if (type.equalsIgnoreCase("error"))
        {
            reply = "Error:\t"+meg+"\n";

        }
        else if (type.equalsIgnoreCase("response"))
        {
            reply = "Response:\t"+meg+"\n";
        }
        else if (type.equalsIgnoreCase("status"))
        {
            reply = "Status:\t"+meg+"\n";
        }
        else if (type.equalsIgnoreCase("command"))
        {
            reply = "Command:\t"+meg+"\n";
        }

        return reply;

    }

    public void writeDoc(JTextPane txtSys, String message, String type) throws BadLocationException
    {

            StyledDocument doc = txtSys.getStyledDocument();        
            doc.insertString(doc.getLength(), messagePrefix(message,type), styleDisplay(type));


    }

}
4

1 回答 1

3

BackSlash 的评论是正确的。您应该避免在 GUI 线程中执行代码,因为它会“冻结”UI,直到代码完成。在您的情况下,连接到远程服务器可能是一项冗长的操作,这就是您看到 UI 挂起的原因。您应该熟悉 Swing 线程模型、事件调度线程 (EDT) 和相关概念。从Oracle 自己的文档开始,我建议您推荐《 Filthy Rich Clients》一书的前几章,这是一本针对富客户端应用程序的好书,其中包含关于 Swing 的所有内容的介绍性章节。

现在对于您的问题,您创建了一个新类,扩展SwingWorker和实现doInBackgroundand donedoInBackground在 EDT 之外执行,因此它不会阻塞您的 UI,并且一旦任务完成就会调用 done。从文档:

final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
    @Override
    public String doInBackground() {
        return findTheMeaningOfLife();
    }

    @Override
    protected void done() {
        try { 
            label.setText(get());
        } catch (Exception ignore) {
        }
    }
}

(new MeaningOfLifeFinder()).execute();

可以说findTheMeaningOfLife是一个潜在的冗长操作。它在 EDIT 之外执行,一旦完成,它将通过执行done.

于 2013-09-09T16:16:03.630 回答