如何在SwingX中使用相对单元格突出显示?

时间:2014-08-18 10:42:52

标签: java swingx jxtable swingx-highlighter

我想突出显示相对于内部值的org.jdesktop.swingx.JXTreeTable中的单元格,如在'突出显示(扩展)'中的SwingX展示中:

i.imgur.com/iw89kqn.png

展示中提供了一些代码,但我无法让它工作,它并没有突出显示任何内容。我无法理解荧光笔与值绑定的位置(可能提供的代码不完整)。此外,没有可用的文档。

以下是展示代码:

这是我的代码:

TreeFrame.java

private void initialize( ProfileThread profileThread )
{
    try
    {
      UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
    }
    catch ( Exception e )
    {
      e.printStackTrace();
    }

    setBounds( 0, 0, 800, 600 );
    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    setTitle( "ProfileLog" );

    NoRootTreeTableModel model = new NoRootTreeTableModel(
        profileThread.getProfileThreadElements(), this );
    JXTreeTable treeTable = new JXTreeTable( model );

    MattePainter painter = new MattePainter( PaintUtils.setAlpha( Color.RED, 125 ) );
    highlighter = new RelativePainterHighlighter( painter );

    highlighter.setHighlightPredicate( HighlightPredicate.ALWAYS );

    treeTable.addHighlighter( highlighter );

    JScrollPane treeView = new JScrollPane( treeTable );
    getContentPane().add( treeView );

    setVisible( true );
  }

  public void setCurrentDuration( long duration )
  {
    DurationRelativizer relativizer = createDurationRelativizer( duration );
    highlighter.setRelativizer( relativizer );
  }

  /**
   * Creates and returns a relativizer with the given intermediate value.
   *
   */
  private DurationRelativizer createDurationRelativizer( long duration )
  {
    return new DurationRelativizer( 0, true, 15000, duration );
  }

  public static class DurationRelativizer extends NumberRelativizer
  {

    public DurationRelativizer( int column, boolean spreadColumns, Number max, Number current )
    {
      super( column, spreadColumns, max, current );
    }

    @Override
    protected Number getNumber( ComponentAdapter adapter )
    {
      if ( !( adapter.getValue( getValueColumn() ) instanceof ProfileThreadElement ) )
      {
        return null;
      }
      return ( (ProfileThreadElement) adapter.getValue( getValueColumn() ) ).getDuration();
    }
  }

我从示例中获取了相关的代码片段,并根据我的要求进行了更改。 我的RelativePainterHighlighter类与展示中的完全相同。

这是我的ProfileThreadElement类:

ProfileThreadElement.java

import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import javax.swing.tree.TreeNode;

public class ProfileThreadElement implements TreeNode
{
  private Date start;
  private Date end;
  private long duration;
  private String text;
  private String result;

  private ProfileThreadElement parent;
  private List<ProfileThreadElement> children;

  /**
   * Instantiates a new profile thread element.
   *
   * @param timestamp the timestamp
   * @param text the text
   */
  public ProfileThreadElement( Date timestamp, String text )
  {
    super();
    this.start = timestamp;
    this.text = text;
    this.children = new ArrayList<ProfileThreadElement>();
  }

  /**
   * Close.
   *
   * @param timestamp the timestamp
   * @param duration the duration
   * @param result the result
   */
  public void close( Date timestamp, long duration, String result )
  {
    this.end = timestamp;
    this.duration = duration;
    this.result = result;

  }

  /**
   * Adds the children.
   *
   * @param child the child
   */
  public void addChildren( ProfileThreadElement child )
  {
    // if ( children == null )
    // {
    // children = new ArrayList<ProfileThreadElement>();
    // }

    children.add( child );
    child.setParent( this );
  }

  /**
   * @param parent the parent to set
   */
  void setParent( ProfileThreadElement parent )
  {
    this.parent = parent;
  }

  /**
   * Checks if is open.
   *
   * @return true, if is open
   */
  public boolean isOpen()
  {
    return end == null;
  }

  /**
   * @return the start
   */
  public Date getStart()
  {
    return start;
  }

  /**
   * @return the end
   */
  public Date getEnd()
  {
    return end;
  }

  /**
   * @return the duration
   */
  public long getDuration()
  {
    return duration;
  }

  /**
   * @return the text
   */
  public String getText()
  {
    return text;
  }

  /**
   * @return the result
   */
  public String getResult()
  {
    return result;
  }

  /**
   * @return the parent
   */
  public ProfileThreadElement getParent()
  {
    return parent;
  }

  /**
   * @return the children
   */
  public List<ProfileThreadElement> getChildren()
  {
    return children;
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.tree.TreeNode#children()
   */
  @Override
  public Enumeration<ProfileThreadElement> children()
  {
    return new Enumeration<ProfileThreadElement>()
    {
      Iterator<ProfileThreadElement> iterator = children.iterator();

      @Override
      public boolean hasMoreElements()
      {
        return iterator.hasNext();
      }

      @Override
      public ProfileThreadElement nextElement()
      {
        return iterator.next();
      }
    };
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.tree.TreeNode#getAllowsChildren()
   */
  @Override
  public boolean getAllowsChildren()
  {
    return !children.isEmpty();
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.tree.TreeNode#getChildAt(int)
   */
  @Override
  public TreeNode getChildAt( int childIndex )
  {
    return children.get( childIndex );
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.tree.TreeNode#getChildCount()
   */
  @Override
  public int getChildCount()
  {
    return children.size();
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.tree.TreeNode#getIndex(javax.swing.tree.TreeNode)
   */
  @Override
  public int getIndex( TreeNode node )
  {
    return children.indexOf( node );
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.tree.TreeNode#isLeaf()
   */
  @Override
  public boolean isLeaf()
  {
    return children.isEmpty();
  }

  @Override
  public String toString()
  {
    StringBuffer sb = new StringBuffer();

    sb.append( duration );
    sb.append( " ms " );
    sb.append( text );

    return sb.toString();
  }
}

我的树桌模型:

NoRootTreeTableModel.java

public class NoRootTreeTableModel extends AbstractTreeTableModel
{
  private final static String[] COLUMN_NAMES = { "Duration (ms)", "Function Call", "Class" };

  private List<ProfileThreadElement> profileThreadElements;
  private TreeFrame frame;

  public NoRootTreeTableModel( List<ProfileThreadElement> profileThreadElements, TreeFrame frame )
  {
    super( new Object() );
    this.profileThreadElements = profileThreadElements;
    this.frame = frame;
  }

  @Override
  public int getColumnCount()
  {
    return COLUMN_NAMES.length;
  }

  @Override
  public String getColumnName( int column )
  {
    return COLUMN_NAMES[column];
  }

  @Override
  public boolean isCellEditable( Object node, int column )
  {
    return false;
  }

  @Override
  public Object getValueAt( Object node, int column )
  {
    if ( node instanceof ProfileThreadElement )
    {
      Matcher matcher;
      Pattern pattern;

      ProfileThreadElement element = (ProfileThreadElement) node;

      switch ( column )
      {
        case 0: // duration
          frame.setCurrentDuration( element.getDuration() );
          return element.getDuration();
        case 1: // function
          pattern = Pattern.compile( "\\.[a-z][a-zA-Z]+\\(.*\\)" );
          matcher = pattern.matcher( element.getText() );
          if ( matcher.find() )
            return matcher.group().substring( 1 );
          else
            return "";
        case 2: // class
          pattern = Pattern.compile( ".+?(?=\\.[a-z][a-zA-Z]+\\(.*\\))" );
          matcher = pattern.matcher( element.getText() );
          if ( matcher.find() )
            return matcher.group().replace( "class ", "" );
          else
            return "";
      }
    }
    return null;
  }

  @Override
  public int getChildCount( Object parent )
  {
    if ( parent instanceof ProfileThreadElement )
    {
      ProfileThreadElement element = (ProfileThreadElement) parent;
      return element.getChildren().size();
    }
    return profileThreadElements.size();
  }

  @Override
  public Object getChild( Object parent, int index )
  {
    if ( parent instanceof ProfileThreadElement )
    {
      ProfileThreadElement element = (ProfileThreadElement) parent;
      return element.getChildren().get( index );
    }
    return profileThreadElements.get( index );
  }

  @Override
  public int getIndexOfChild( Object parent, Object child )
  {
    ProfileThreadElement element = (ProfileThreadElement) parent;
    return element.getChildren().indexOf( (ProfileThreadElement) child );
  }
}

我认为最大的问题是我不知道在哪里调用TreeFrame.setCurrentDuration(...)方法。展示演示中缺少这个。有人有相对突出的工作吗?

感谢任何帮助,提前谢谢!

PS:如果我错过了某些内容或者您需要更多信息,请告诉我!

1 个答案:

答案 0 :(得分:0)

我已经切断了我不需要的所有东西,并注意到doHighlight(..)从未被调用过。原因是canHighlight(..)返回false,因为我的relativizer为null。