1

「強調表示 (拡張)」の下の SwingX ショーケースのように、内部の値に関連して org.jdesktop.swingx.JXTreeTable のセルを強調表示したい:

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: 何か見逃した場合や、さらに詳しい情報が必要な場合は、お知らせください。

4

1 に答える 1

0

不要なものをすべて切り取ったところ、doHighlight(..) が呼び出されていないことに気付きました。その理由は、相対化子が null だったために canHighlight(..) が false を返したためです。

于 2014-08-25T12:18:54.993 に答える