Skip to main content

JEditorPane HTML and setCaretPosition( Test Code Included ). Aka "What??"

6 replies [Last post]
leouser
Offline
Joined: 2005-12-12
Points: 0

Hi,

I was doing some work with some simple HTML display and the EditorPane in HTML viewer mode. Everythin was going fine until I tried to set the caret position in the Editor. I tried to set it based off the text returned from the JEditorPane but then it throws an Exception. Why? Well it appears that the text returned from the Document is much much smaller than the text returned from the EditorPane. Code to illustrate this:
//@+leo-ver=4-thin
//@+node:zorcanda!.20051212211237:@thin ShowHTMLWeirdness.java
//@@language java

import javax.swing.*;
import javax.swing.text.*;
import java.util.Arrays;
import static java.lang.System.out;

public class ShowHTMLWeirdness{

public static void main( String[] args ){

Runnable run = new Runnable(){

public void run(){

//@ <>
//@+node:zorcanda!.20051212211237.1:<>
JFrame jf = new JFrame();
JEditorPane jep = new JEditorPane();
jep.setContentType( "text/html" );
String content = "

Hi!\n"+
                "How's it going?\n"+
                "Why am I here?\n"+
                "For amusement no less\n"+
                "
";
jep.setText( content );
JScrollPane jsp = new JScrollPane( jep );
jf.add( jsp );
jf.pack();
jf.setVisible( true );

char[] c = new char[ 15 ];
Arrays.fill( c, '-' );
String breaker = new String( c );
out.println( breaker );
String jeptext = jep.getText();
out.println( jeptext );
out.println( jeptext );
try{
out.println( breaker );
Document doc = jep.getDocument();
out.println( doc.getText( 0, doc.getLength() ) );
out.println( doc.getLength() );
jep.setCaretPosition( doc.getLength() );
jep.setCaretPosition( jeptext.length() );

}
catch( BadLocationException ble ){

ble.printStackTrace();

}
/*
setCaretPosition

public void setCaretPosition(int position)

Sets the position of the text insertion caret for the TextComponent. Note that the caret tracks change, so this may move if the underlying text of the component is changed. If the document is null, does nothing. The position must be between 0 and the length of the component's text or else an exception is thrown.
*/

//@-node:zorcanda!.20051212211237.1:<>
//@nl

}

};
SwingUtilities.invokeLater( run );

}

}
//@nonl
//@-node:zorcanda!.20051212211237:@thin ShowHTMLWeirdness.java
//@-leo

------
Im not sure what to say, it appears I must get the Text from the Document and set the Caret position based off of that. Though this seems to break the contract of the JEditorPane API which says:
public void setCaretPosition(int position)

Sets the position of the text insertion caret for the TextComponent. Note that the caret tracks change, so this may move if the underlying text of the component is changed. If the document is null, does nothing. The position must be between 0 and the length of the component's text or else an exception is thrown.

-----
my interpretation of this is that the component's text is that which would be returned by getText of JEditorPane.

So Im confused! :D
is this a bug, or am I missing something?
leouser

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
idk
Offline
Joined: 2005-01-12
Points: 0

Hi,

you might want to try
[code]
jep.setCaretPosition(doc.getLength() - 1);
[/code]

>my interpretation of this is that the component's text is that which would be returned by getText of JEditorPane.

text component operates in terms of document model.
getText returns "pretty printing" of the document model.

Thanks,
Igor

leouser
Offline
Joined: 2005-12-12
Points: 0

Intriguingly confusing! :D Thanks for the reply.

Interesting, so if you feed JEditorPane in HTML mode an HTML document you must operate in terms of how the document has transformed your text. This certainly could complicate searching and setting the caret based off of a doc you passed in. Want to search for:

  • meow
  • when there is a meow

    get the pretty printed text, search based off of that and somehow translate back to the model.

    interesting stuff,
    leouser

    idk
    Offline
    Joined: 2005-01-12
    Points: 0

    >get the pretty printed text, search based off of that and somehow translate back to the model.

    One can search in the document model directly.
    Searching for "meow" is simple, searching for
    "

  • meow
  • " is more involved. One would have to know
    how different tags are represented in the model...

    -Igor

    raydelto
    Offline
    Joined: 2004-07-14
    Points: 0

    jeptext.length() -1 worked for me.

    I am coding a chat client. My issue was that when i received a new message the caret went to initial position. The following code made my JEditorPane to show the latest received message:

    public void receiveMessage(String receivedMessage){
    sbMessages.append(""+ receivedMessage+":
    ");
    sbMessages.setText(sbMessages.toString());
    sbMessages.setCaretPosition(edtMensajes.getDocument().getLength() -1);
    }

    where sbMessages is a StringBuffer. (I tried to do it more efficiently with insertString method from Document class, but i didnt got it to work with html content type).

    doug.greaves
    Offline
    Joined: 2006-02-14
    Points: 0

    Since you are using HTML, jeptext.length() returns a length that includes the HTML tags while doc.getLength() returns a length only covering the displayed text. Also, setCaretPosition() operates relative to the displayed text, not the full text [including the HTML tags].

    This can all be seen in the System.out's you have in your code.

    leouser
    Offline
    Joined: 2005-12-12
    Points: 0

    I should not that this line:

    jep.setCaretPosition( jeptext.length() );

    probably should be:

    jep.setCaretPosition( jeptext.length() -1 );

    This still throws the BadLocationException with the change in place.

    leouser