我正在尝试使用JEditorPane来显示一些HTML文本。出于某种原因,我必须使用setText()方法。然而,这使得JEditorPane闪烁。原因是每次更新 editorPane.setText(msgBuffer); 后,我必须将光标移到文档 editorPane.setCaretPosition((editorPane.getDocument())的末尾.getLength ()-1)因为我希望最近的文本行出现在文档的底部。 我很聪明你们整个代码让你自己看看。我已经看到很多关于使用document.insertString的建议,但就此而言,我必须使用不属于我感兴趣的个别属性。 有没有办法让这段代码无闪烁?
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("-----------------------");
}
}
}
答案 0 :(得分:5)
您不应修改EDT之外的UI组件。
如果您在 updateMessages 中添加一个电话,以便在EDT上进行更新,那么闪烁就会消失。
例如:
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);
}
}
});
}
请注意,您不应该在EDT上执行长时间运行操作,否则您将“锁定”您的UI。
答案 1 :(得分:0)
如果您有一个长时间运行的IO并且之后更新了GUI,则可以使用SwingWorker
代替http://en.wikipedia.org/wiki/Event_dispatching_thread)
SwingWorker<Document, Void> worker = new SwingWorker<Document, Void>() {
public Document doInBackground() throws IOException {
return loadXML(); // heavy task
}
public void done() {
try {
Document doc = get();
display(doc);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
worker.execute();