I am trying to use JEditorPane to display some HTML text. For some reason I have to use setText() method. However that makes the JEditorPane flickering. The reason is that every time after updating the editorPane.setText(msgBuffer); I have to bring the cursor to the end of document editorPane.setCaretPosition((editorPane.getDocument()).getLength()-1) asI want the most recent text line appearing at the bottom of the document. I have bright you guys the entire code for you to see it for yourself. I have seen many recommendations as to use document.insertString, but for that matter I have to use individual attributes which is not of my interest. Is there any way to make this code run flicker free?
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
public class CMessageWindow {
private static final String ERROR = "ERROR";
private static final String MESSAGE = "msg";
private JScrollPane scrollPane;
public JEditorPane editorPane;
private HTMLEditorKit kit;
private String msgBuffer=new String("");
private static CMessageWindow window=null;
private static JFrame frameContainer=null;
private CMessageWindow()
{
editorPane = new JEditorPane ();
editorPane.setEditable(false);
editorPane.setContentType("text/html");
kit = new HTMLEditorKit();
editorPane.setEditorKit(kit);
StyleSheet styleSheet = kit.getStyleSheet();
styleSheet.addRule("."+MESSAGE+" {font: 10px monaco; color: black; }");
styleSheet.addRule("."+ERROR+" {font: 10px monaco; color: #ff2222; background-color : #cccccc; }");
Document doc = kit.createDefaultDocument();
editorPane.setDocument(doc);
scrollPane = new JScrollPane(editorPane);
}
public static CMessageWindow getInstance(){
if (null==window)
{window=new CMessageWindow();}
return window;
}
/**
* The core
* @param sMessage
* @param sType
*/
private void updateMessages(final String sMessage, final String sType)
{
String sMessageHTML="";
String sTypeText="";
if (!sMessage.equals("\r\n")){
sTypeText = sType+": ";
}
sMessageHTML = sMessage.replaceAll("(\r\n|\n)", "<br/>");
if (!sMessageHTML.equals("<br/>"))
{
sMessageHTML = "<SPAN CLASS="+sType+">"+ sTypeText+sMessageHTML + "</SPAN>";
}
msgBuffer=msgBuffer.concat( sMessageHTML);
editorPane.setText(msgBuffer);
if ((editorPane.getDocument()).getLength()>1){
editorPane.setCaretPosition((editorPane.getDocument()).getLength()-1);
}
}
public void setContainerFrame(JFrame jFrame){
frameContainer = jFrame;
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(frameContainer.getContentPane());
frameContainer.getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollPane)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 217, Short.MAX_VALUE))
);
}
public void setVisible(boolean bVisible){
editorPane.setVisible(bVisible);
scrollPane.setVisible(bVisible);
}
public void printMsg(String sMessage){
String sType = MESSAGE;
updateMessages(sMessage,sType);
}
public void printlnMsg(String sMessage){
sMessage=sMessage.concat("\r\n");
printMsg(sMessage);
}
public void printErr(String sMessage){
String sType = ERROR;
updateMessages(sMessage,sType);
}
public void printlnErr(String sMessage){
sMessage=sMessage.concat("\r\n");
printErr(sMessage);
}
public static void main(String args[]){
CMessageWindow m_LogMgr;
JFrame frame = new JFrame();
m_LogMgr=CMessageWindow.getInstance();
m_LogMgr.setContainerFrame(frame);
frame.setVisible(true);
frame.setSize(500, 500);
for(int i=0;i<20;++i){
m_LogMgr.printlnErr("MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM");
}
for(int i=0;i<150;++i){
try {
Thread.sleep(20);
} catch (Exception e) {
}
m_LogMgr.printlnMsg("-----------------------");
}
}
}
You should not modify UI components outside the EDT.
If you add a call inside, say, your updateMessages so that the update happens on the EDT then the flicker goes away.
For example:
private void updateMessages(final String sMessage, final String sType)
{
SwingUtilities.invokeLater( new Runnable() {
public void run() {
String sMessageHTML="";
String sTypeText="";
if (!sMessage.equals("\r\n")){
sTypeText = sType+": ";
}
sMessageHTML = sMessage.replaceAll("(\r\n|\n)", "<br/>");
if (!sMessageHTML.equals("<br/>"))
{
sMessageHTML = "<SPAN CLASS="+sType+">"+ sTypeText+sMessageHTML + "</SPAN>";
}
msgBuffer=msgBuffer.concat( sMessageHTML);
editorPane.setText(msgBuffer);
if ((editorPane.getDocument()).getLength()>1){
editorPane.setCaretPosition((editorPane.getDocument()).getLength()-1);
}
}
});
}
Note that you shouldn't perform long running operations on the EDT because otherwise you'll "lock" your UI.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With