简体   繁体   中英

Code refuses to display text in JTextArea

I created a JTextArea to show messages in multiple colours while the program is running. I use NetBeans 8.0, and I added a JTextArea to the jFrame called "log" before writing the code.

First, I defined a class called apppane :

private void apppane(JTextPane log, String msg, Color c)
{
    /*This allows multi-colour inside the logging pane*/
    StyleContext sc = StyleContext.getDefaultStyleContext();
    AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);

    aset = sc.addAttribute(aset, StyleConstants.FontFamily, "Lucida Console");
    aset = sc.addAttribute(aset, StyleConstants.Alignment, StyleConstants.ALIGN_JUSTIFIED);

    int len = log.getDocument().getLength();
    log.setCaretPosition(len);
    log.setCharacterAttributes(aset, false);
    log.replaceSelection(msg);
}

Next, I wrote the code to display the text in colours:

/*time1 gets the current system time and it works perfectly, no errors there*/
 private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    // TODO add your handling code here:
    Thread t1;
    FTPClient cli=new FTPClient();
    FTPClientConfig conf=new FTPClientConfig();
    boolean err=false;

    try{
        String ServAddress="195.191.24.202";
        int reply;
       TimeNow time1=new TimeNow();
        apppane(log,time1.whatsthetime()+": Connecting to "+ServAddress+"\n",Color.RED);
        System.out.println(time1.whatsthetime()+": Connecting to "+ServAddress+"\n");
        cli.connect(ServAddress);
        cli.configure(conf);
        TimeNow time2=new TimeNow();
        apppane(log,time2.whatsthetime()+": Connected to "+ServAddress,Color.BLUE);
        System.out.println(time2.whatsthetime()+": Connected to "+ServAddress+"\n");
        System.out.println(time2.whatsthetime()+": "+cli.getReplyString());
        reply=cli.getReplyCode();
        if(!FTPReply.isPositiveCompletion(reply)){
            cli.disconnect();
           TimeNow time3=new TimeNow();
            apppane(log,time3.whatsthetime()+": Connection rejected. \n", Color.RED);
           System.out.println(time3.whatsthetime()+": Connectiion failed \n");
        }
        log.setText(ServAddress);
    }
    catch (Exception e){
        e.printStackTrace();
    }
}                              

But, no text appears in the JTextPane. Help please!

SUSPICION: Am I defining a new JTextPane when I ain't?

UPDATE 1: Here's the Swing GUI code generated by NetBeans:

private void initComponents() {

    dochello = new javax.swing.JLabel();
    jButton1 = new javax.swing.JButton();
    jScrollPane2 = new javax.swing.JScrollPane();
    log = new javax.swing.JTextPane();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("MayvilFTP");
    getContentPane().setLayout(null);

    dochello.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
    dochello.setText("Welcome, Dr. ");
    getContentPane().add(dochello);
    dochello.setBounds(10, 30, 350, 30);

    jButton1.setText("Connect");
    jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });
    getContentPane().add(jButton1);
    jButton1.setBounds(370, 30, 110, 23);

    log.setEditable(false);
    log.setOpaque(false);
    jScrollPane2.setViewportView(log);

    getContentPane().add(jScrollPane2);
    jScrollPane2.setBounds(10, 230, 480, 110);

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

Your text will not display until the whole jButton1ActionPerformed method returns.

Your code is running in the Swing event thread. This is the same thread which will actually do the painting of your component... and process all other events. So your GUI will be essentially frozen while the FTP is in progress.

If you are performing an operation that takes some time, you should start that in a new thread. You should not perform an FTP operation within a button press event.

You create a variable Thread t1 but never use it. Why don't you do the FTP in this thread, and use java.awt.EventQueue.invokeLater to call apppane at the appropriate moments?

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
  Thread t1 = new Thread(new Runnable() { public void run(){
    apppane_threadsafe( ... );
    // do your ftp stuff
    apppane_threadsafe( ... );
  }});
  t1.start();
}

and

private void apppane_threadsafe(JTextPane log, String msg, Color c){
  EventQueue.invokeLater(new Runnable() { public void run() {  
    apppane(log, msg, c);
  }
}}

Short answer: the setEditable(false) and replaceSelection() wont work together.

Long answer: Check replaceSelection() method in JTextPane . It will work only for an editable JTextPane.

@Override
public void replaceSelection(String content) {
    replaceSelection(content, true);
}

private void replaceSelection(String content, boolean checkEditable) {
    if (checkEditable && !isEditable()) {
        UIManager.getLookAndFeel().provideErrorFeedback(JTextPane.this);
        return;
    }
    ...
}

The simplest solution is to set the pane to editable, make the changes and set back to uneditable. But this is ugly.
A better solution is to manipulate the underlying Document .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM