Java Swing 文本字段中的 ANSI 颜色

发布于 2024-11-27 16:52:40 字数 77 浏览 2 评论 0原文

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

Is there any simple way to parse Ansi colors in log files, and use it in text fields in Swing (JTextArea, JTextPAne,...)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凶凌 2024-12-04 16:52:40

没有尝试过,但是这里有一些代码(需要一些格式来看起来不错),它声称是 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; }
  }
}

Not tried it, but there's some code here (which needs some formatting to look nice) which claims to be an ANSI colored JTextPane subclass...


For posterity, here is the class run through NetBeans to format the code

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; }
  }
}
故事灯 2024-12-04 16:52:40

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

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();}
}

这个方法似乎更加健壮,并且适用于我尝试过的所有情况,但我还没有测试过它完整

此方法的工作原理是在文档末尾插入彩色文本,而不是替换不存在的文本,如果它是不可编辑的,只会导致重复的 Windows 错误声音,这非常烦人

If youre JTextPane is non-editable then tim_yates method will not work, to improve upon his method I replaced his append method with

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();}
}

This method seems to be much more robust and works in all of the cases I have tried, but I have not tested it in full

This method works by inserting colored text at the end of the document rather than replacing text that don't exist, which if it is non-editable just results in a repeated windows error sound which is quite annoying

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文