Java Swing 文本字段中的 ANSI 颜色

问题描述 投票:0回答:3

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

java swing ansi-colors
3个回答
13
投票

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

5
投票

如果你的 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 错误声音,这非常烦人


0
投票

我现在这是一个旧线程。但如果有人过来的话,我在 JEditorPane 中使用 AnsiEditorKit 等创建了一些类来支持 ANSI: https://github.com/flemming-n-larsen/java-swing-ansi-support

© www.soinside.com 2019 - 2024. All rights reserved.