Java Swing 文本字段中的 ANSI 颜色

Posted

技术标签:

【中文标题】Java Swing 文本字段中的 ANSI 颜色【英文标题】:ANSI colors in Java Swing text fields 【发布时间】:2011-10-17 11:25:46 【问题描述】:

有没有简单的方法来解析日志文件中的 Ansi 颜色,并在 Swing 中的文本字段中使用它(JTextArea,JTextPAne,...)?

【问题讨论】:

我怀疑有一个简单的方法。您是否看过一些开源终端仿真器?另外,生成日志文件的原因是什么? 【参考方案1】:

如果你的 JTextPane 是不可编辑的,那么 tim_yates 方法将不起作用,为了改进他的方法,我将他的 append 方法替换为

public void append(Color c, String s) 
    StyleContext sc = StyleContext.getDefaultStyleContext();
    AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
    int len = getDocument().getLength(); 
    try getDocument().insertString(len, s, aset); 
    catch (BadLocationException e) e.printStackTrace();

这种方法似乎更健壮,在我尝试过的所有情况下都有效,但我还没有完全测试过

此方法通过在文档末尾插入彩色文本而不是替换不存在的文本来工作,如果它是不可编辑的,只会导致重复的窗口错误声音,这很烦人

【讨论】:

【参考方案2】:

没有尝试过,但有 some code here(需要一些格式才能看起来不错)声称是 ANSI 彩色的 JTextPane 子类...


为了后代,这里是通过 NetBeans 运行以格式化代码的类

import javax.swing.*;
import javax.swing.text.*;
import java.awt.Color;

public class ColorPane extends JTextPane 
  static final Color D_Black   = Color.getHSBColor( 0.000f, 0.000f, 0.000f );
  static final Color D_Red     = Color.getHSBColor( 0.000f, 1.000f, 0.502f );
  static final Color D_Blue    = Color.getHSBColor( 0.667f, 1.000f, 0.502f );
  static final Color D_Magenta = Color.getHSBColor( 0.833f, 1.000f, 0.502f );
  static final Color D_Green   = Color.getHSBColor( 0.333f, 1.000f, 0.502f );
  static final Color D_Yellow  = Color.getHSBColor( 0.167f, 1.000f, 0.502f );
  static final Color D_Cyan    = Color.getHSBColor( 0.500f, 1.000f, 0.502f );
  static final Color D_White   = Color.getHSBColor( 0.000f, 0.000f, 0.753f );
  static final Color B_Black   = Color.getHSBColor( 0.000f, 0.000f, 0.502f );
  static final Color B_Red     = Color.getHSBColor( 0.000f, 1.000f, 1.000f );
  static final Color B_Blue    = Color.getHSBColor( 0.667f, 1.000f, 1.000f );
  static final Color B_Magenta = Color.getHSBColor( 0.833f, 1.000f, 1.000f );
  static final Color B_Green   = Color.getHSBColor( 0.333f, 1.000f, 1.000f );
  static final Color B_Yellow  = Color.getHSBColor( 0.167f, 1.000f, 1.000f );
  static final Color B_Cyan    = Color.getHSBColor( 0.500f, 1.000f, 1.000f );
  static final Color B_White   = Color.getHSBColor( 0.000f, 0.000f, 1.000f );
  static final Color cReset    = Color.getHSBColor( 0.000f, 0.000f, 1.000f );
  static Color colorCurrent    = cReset;
  String remaining = "";

  public void append(Color c, String s) 
    StyleContext sc = StyleContext.getDefaultStyleContext();
    AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
    int len = getDocument().getLength(); // same value as getText().length();
    setCaretPosition(len);  // place caret at the end (with no selection)
    setCharacterAttributes(aset, false);
    replaceSelection(s); // there is no selection, so inserts at caret
  

  public void appendANSI(String s)  // convert ANSI color codes first
    int aPos = 0;   // current char position in addString
    int aIndex = 0; // index of next Escape sequence
    int mIndex = 0; // index of "m" terminating Escape sequence
    String tmpString = "";
    boolean stillSearching = true; // true until no more Escape sequences
    String addString = remaining + s;
    remaining = "";

    if (addString.length() > 0) 
      aIndex = addString.indexOf("\u001B"); // find first escape
      if (aIndex == -1)  // no escape/color change in this string, so just send it with current color
        append(colorCurrent,addString);
        return;
      
// otherwise There is an escape character in the string, so we must process it

      if (aIndex > 0)  // Escape is not first char, so send text up to first escape
        tmpString = addString.substring(0,aIndex);
        append(colorCurrent, tmpString);
        aPos = aIndex;
      
// aPos is now at the beginning of the first escape sequence

      stillSearching = true;
      while (stillSearching) 
        mIndex = addString.indexOf("m",aPos); // find the end of the escape sequence
        if (mIndex < 0)  // the buffer ends halfway through the ansi string!
          remaining = addString.substring(aPos,addString.length());
          stillSearching = false;
          continue;
        
        else 
          tmpString = addString.substring(aPos,mIndex+1);
          colorCurrent = getANSIColor(tmpString);
        
        aPos = mIndex + 1;
// now we have the color, send text that is in that color (up to next escape)

        aIndex = addString.indexOf("\u001B", aPos);

        if (aIndex == -1)  // if that was the last sequence of the input, send remaining text
          tmpString = addString.substring(aPos,addString.length());
          append(colorCurrent, tmpString);
          stillSearching = false;
          continue; // jump out of loop early, as the whole string has been sent now
        

        // there is another escape sequence, so send part of the string and prepare for the next
        tmpString = addString.substring(aPos,aIndex);
        aPos = aIndex;
        append(colorCurrent, tmpString);

       // while there's text in the input buffer
    
  

  public Color getANSIColor(String ANSIColor) 
    if (ANSIColor.equals("\u001B[30m"))         return D_Black; 
    else if (ANSIColor.equals("\u001B[31m"))    return D_Red; 
    else if (ANSIColor.equals("\u001B[32m"))    return D_Green; 
    else if (ANSIColor.equals("\u001B[33m"))    return D_Yellow; 
    else if (ANSIColor.equals("\u001B[34m"))    return D_Blue; 
    else if (ANSIColor.equals("\u001B[35m"))    return D_Magenta; 
    else if (ANSIColor.equals("\u001B[36m"))    return D_Cyan; 
    else if (ANSIColor.equals("\u001B[37m"))    return D_White; 
    else if (ANSIColor.equals("\u001B[0;30m"))  return D_Black; 
    else if (ANSIColor.equals("\u001B[0;31m"))  return D_Red; 
    else if (ANSIColor.equals("\u001B[0;32m"))  return D_Green; 
    else if (ANSIColor.equals("\u001B[0;33m"))  return D_Yellow; 
    else if (ANSIColor.equals("\u001B[0;34m"))  return D_Blue; 
    else if (ANSIColor.equals("\u001B[0;35m"))  return D_Magenta; 
    else if (ANSIColor.equals("\u001B[0;36m"))  return D_Cyan; 
    else if (ANSIColor.equals("\u001B[0;37m"))  return D_White; 
    else if (ANSIColor.equals("\u001B[1;30m"))  return B_Black; 
    else if (ANSIColor.equals("\u001B[1;31m"))  return B_Red; 
    else if (ANSIColor.equals("\u001B[1;32m"))  return B_Green; 
    else if (ANSIColor.equals("\u001B[1;33m"))  return B_Yellow; 
    else if (ANSIColor.equals("\u001B[1;34m"))  return B_Blue; 
    else if (ANSIColor.equals("\u001B[1;35m"))  return B_Magenta; 
    else if (ANSIColor.equals("\u001B[1;36m"))  return B_Cyan; 
    else if (ANSIColor.equals("\u001B[1;37m"))  return B_White; 
    else if (ANSIColor.equals("\u001B[0m"))     return cReset; 
    else  return B_White; 
  

【讨论】:

tim_yates :我已经检查了您链接中的代码并且它正在工作:) 您能否发布或提供此 Java 类的正确格式版本的链接? 谢谢 :) 我确实尝试过使用 eclipse 格式化程序,结果得到了一堆不可分割的 cmets 和代码!

以上是关于Java Swing 文本字段中的 ANSI 颜色的主要内容,如果未能解决你的问题,请参考以下文章

Java-Swing:使用 HTML 设置选定的文本颜色

Java,Swing,获取和更改所有输入字段

我必须使用哪个 Swing 组件在 java 的同一字段中应用不同样式的文本

按住键时,Swing 中的文本输入字段在 OS X 上停止工作

text BASH:为ANSI文本颜色转义序列设置变量

解释使用java创建文本字段的代码[关闭]