2014-05-23 9 views
1

을 다시 그리기. 내가 JXTreeTable을 넣었을 때, 나는 웬일인지 그 줄이 자동으로 줄무늬를 가지지 않는 것을 알아 차렸다. JXTreeTable, 행 스트라이핑과 적절한 나는 모양을 사용하여 기본적으로 테이블의 행 스트라이핑을 수행하는 느낌이있어

그래서 나는 형광펜을 사용하여 문제를 해결하는 듯했지만 나는 다시 그리기 결함 얻을 것 같습니다 :

screenshot showing the painting glitch

그것은 특별히 대신 전체 셀의 텍스트의 경계를 재 도장되어 JXTreeTable 것 같아를 . 이유를 알아 내기 위해 디버거에서이 문제를 잡아 내려고 노력했지만 프로그램간에 전환 할 때마다 전체 창이 다시 표시되므로이 종류의 것을 잡는 것이 거의 불가능합니다.

JTableJTree은 모두 올바로 수행 동작합니다. 이 모양과 느낌은 (Quaqua와 Synth와 같은) JTree의 행 전체를 그리는 것이므로 어쩌면 그것과 관련이 있습니다. 아마도 JXTreeTable에는 모양과 느낌이 트리의 행을 페인트하지 않는다는 가정이 있습니다. 그렇다면 해결 방법이 있습니까? 이 룩앤필에 문제가있는 것은 아닙니다.

코드 : 1 라운드

import org.jdesktop.swingx.JXTreeTable; 
import org.jdesktop.swingx.decorator.AbstractHighlighter; 
import org.jdesktop.swingx.decorator.ComponentAdapter; 
import org.jdesktop.swingx.decorator.Highlighter; 
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; 
import org.jdesktop.swingx.treetable.DefaultTreeTableModel; 
import org.jdesktop.swingx.treetable.TreeTableModel; 
import org.trypticon.haqua.HaquaLookAndFeel; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.WindowConstants; 
import java.awt.BorderLayout; 
import java.awt.Component; 
import java.util.Arrays; 

public class TreeTableDemo2 implements Runnable { 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new TreeTableDemo2()); 
    } 

    @Override 
    public void run() { 
     try { 
      UIManager.setLookAndFeel(new HaquaLookAndFeel()); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 

     JFrame frame = new JFrame("Tree Table Demo"); 
     frame.setLayout(new BorderLayout()); 
     frame.add(createPanel(), BorderLayout.CENTER); 
     frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public JPanel createPanel() { 
     JPanel panel = new JPanel(new BorderLayout()); 

     TreeTableModel treeTableModel = new DummyTreeTableModel(); 
     JXTreeTable treeTable = new FixedTreeTable(treeTableModel); 
     JScrollPane treeTableScroll = new JScrollPane(treeTable); 

     panel.add(treeTableScroll, BorderLayout.CENTER); 
     return panel; 
    } 

    private static class FixedTreeTable extends JXTreeTable { 
     private static final Highlighter oddRowHighlighter = new AbstractHighlighter() { 
      @Override 
      protected Component doHighlight(Component component, ComponentAdapter componentAdapter) { 
       if (componentAdapter.row % 2 != 0 && 
         !componentAdapter.isSelected()) { 
        component.setBackground(UIManager.getColor("Table.alternateRowColor")); 
       } 
       return component; 
      } 
     }; 

     public FixedTreeTable(TreeTableModel treeModel) { 
      super(treeModel); 

      // This hack makes it paint correctly after releasing the mouse, which is not quite good enough. 
//   getSelectionModel().addListSelectionListener(new ListSelectionListener() { 
//    @Override 
//    public void valueChanged(ListSelectionEvent e) { 
//     Rectangle repaintRange = getCellRect(e.getFirstIndex(), 0, true); 
//     repaintRange.add(getCellRect(e.getLastIndex(), 0, true)); 
//     repaint(repaintRange); 
//    } 
//   }); 
     } 

     @Override 
     public void updateUI() { 
      removeHighlighter(oddRowHighlighter); 

      super.updateUI(); 

      // JTable does this striping automatically but JXTable's default renderer 
      // seems to ignore it, so JXTreeTable inherits this broken behaviour. 
      if (UIManager.get("Table.alternateRowColor") != null) { 
       addHighlighter(oddRowHighlighter); 
      } 
     } 
    } 

    private static class DummyTreeTableNode extends DefaultMutableTreeTableNode { 
     private final Object[] values; 

     private DummyTreeTableNode(String name) { 
      super(name); 
      values = new Object[5]; 
      values[0] = name; 
     } 

     private DummyTreeTableNode(Object... values) { 
      super(values[0]); 
      this.values = values; 
     } 

     @Override 
     public Object getValueAt(int column) { 
      return values[column]; 
     } 
    } 

    private static class DummyTreeTableModel extends DefaultTreeTableModel { 
     private static DefaultMutableTreeTableNode rootNode = new DefaultMutableTreeTableNode(); 
     static { 
      DefaultMutableTreeTableNode blue = new DefaultMutableTreeTableNode("Blue"); 
      blue.add(new DummyTreeTableNode("Orionis C",   33000, 30000.0, 18.0, 5.90)); 
      rootNode.add(blue); 

      DefaultMutableTreeTableNode bluish = new DefaultMutableTreeTableNode("Bluish"); 
      bluish.add(new DummyTreeTableNode("Becrux",    30000, 16000.0, 16.0, 5.70)); 
      bluish.add(new DummyTreeTableNode("Spica",    22000, 8300.0,  10.5, 5.10)); 
      bluish.add(new DummyTreeTableNode("Achernar",   15000, 750.0,  5.40, 3.70)); 
      bluish.add(new DummyTreeTableNode("Rigel",    12500, 130.0,  3.50, 2.70)); 
      rootNode.add(bluish); 

      DefaultMutableTreeTableNode blueWhite = new DefaultMutableTreeTableNode("Blue-White"); 
      blueWhite.add(new DummyTreeTableNode("Sirius A",   9500, 63.0,  2.60, 2.30)); 
      blueWhite.add(new DummyTreeTableNode("Fomalhaut",   9000, 40.0,  2.20, 2.00)); 
      blueWhite.add(new DummyTreeTableNode("Altair",    8700, 24.0,  1.90, 1.80)); 
      rootNode.add(blueWhite); 

      DefaultMutableTreeTableNode white = new DefaultMutableTreeTableNode("White"); 
      white.add(new DummyTreeTableNode("Polaris A",   7400, 9.0,  1.60, 1.50)); 
      white.add(new DummyTreeTableNode("Eta Scorpii",  7100, 6.3,  1.50, 1.30)); 
      white.add(new DummyTreeTableNode("Procyon A",   6400, 4.0,  1.35, 1.20)); 
      rootNode.add(white); 

      DefaultMutableTreeTableNode yellowWhite = new DefaultMutableTreeTableNode("Yellow-White"); 
      yellowWhite.add(new DummyTreeTableNode("Alpha Centauri A", 5900, 1.45,  1.08, 1.05)); 
      yellowWhite.add(new DummyTreeTableNode("The Sun",   5800, 100.0,  1.00, 1.00)); 
      yellowWhite.add(new DummyTreeTableNode("Mu Cassiopeiae",  5600, 0.70,  0.95, 0.91)); 
      yellowWhite.add(new DummyTreeTableNode("Tau Ceti",   5300, 0.44,  0.85, 0.87)); 
      rootNode.add(yellowWhite); 

      DefaultMutableTreeTableNode orange = new DefaultMutableTreeTableNode("Orange"); 
      orange.add(new DummyTreeTableNode("Pollux",    5100, 0.36,  0.83, 0.83)); 
      orange.add(new DummyTreeTableNode("Epsilon Eridani", 4830, 0.28,  0.78, 0.79)); 
      orange.add(new DummyTreeTableNode("Alpha Centauri B", 4370, 0.18,  0.68, 0.74)); 
      rootNode.add(orange); 

      DefaultMutableTreeTableNode red = new DefaultMutableTreeTableNode("Red"); 
      red.add(new DummyTreeTableNode("Lalande 21185",  3400, 0.03,  0.33, 0.36)); 
      red.add(new DummyTreeTableNode("Ross 128",   3200, 0.0005,  0.20, 0.21)); 
      red.add(new DummyTreeTableNode("Wolf 359",   3000, 0.0002,  0.10, 0.12)); 
      rootNode.add(red); 
     } 

     private static final Object[] columnNames = { 
       "Star", "Temperature (K)", "Luminosity", "Mass", "Radius" 
     }; 

     public DummyTreeTableModel() { 
      super(rootNode, Arrays.asList(columnNames)); 
     } 

     @Override 
     public Class<?> getColumnClass(int columnIndex) { 
      if (columnIndex == 0) { 
       return String.class; 
      } else { 
       return Double.class; 
      } 
     } 

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

추가 조사 : 나는 마침내 JXTreeTable에 페인트 방법을 보면서 함정에 디버거의 상태를 관리

.

iconRect = {[email protected]}"java.awt.Rectangle[x=20,y=92,width=16,height=16]" 
textRect = {[email protected]}"java.awt.Rectangle[x=20,y=-17,width=62,height=15]" 
itemRect = {[email protected]}"java.awt.Rectangle[x=20,y=36,width=103,height=18]" 

나는 아직, 확실히 사각형을 그리는이 값을 사용하고 있음을 확인하지 않은하지만 : 내가 볼 것은 그들이 의심스러운 행동에 해당 같이 일부 필드를 가지고있는 ClippedTreeCellRenderer 뭔가라는 점이다 textRect은 정확히 다시 그리는 작은 창 크기입니다. 이제 질문은, 지구상에서 JXTreeTable이이 값들을 끌어 당기는 이유와 그것들을 사용하는 이유는 무엇입니까?

내 본능은 JXTreeTable의 렌더러가 트리 셀 렌더러를 사용하여 직접 트리 자체에 페인트를 지정하는 대신 셀을 직접 렌더링한다고 말합니다. 행 배경 및 확장/축소 아이콘을 페인팅하는 논리는 셀이 아닌 트리에 있으므로 트리밍을 수행하는 경우 트리가 일관되게 페인팅되지 않습니다. 2 라운드

추가 조사 :

는 내가 완전히 잘못된 길이었다 생각합니다. 그것은 가 페인트되는입니다 전체 행처럼 보이지만 tree.isPathSelected (경로) 새로 선택된 파란색 행에 대한 false를 반환하고 방금 해제 행에 대해 true을 반환합니다.

DefaultTreeSelectionModel의 중단 점을 통해 마우스를 놓은 후에 트리 선택이 업데이트된다는 것을 확인할 수 있습니다. 따라서 결국 마우스 오른쪽 단추가 올바르게 렌더링됩니다.

나는 동기 사람들을 유지 어떻게 볼 JXTreeTable에 더 발굴해야합니다.

답변

0

버그를 발견했습니다.당신이 if 검사, 모든 것이 제대로 작동 제거하는 경우

/** 
    * Class responsible for calling updateSelectedPathsFromSelectedRows 
    * when the selection of the list changse. 
    */ 
    class ListSelectionHandler implements ListSelectionListener { 
     @Override 
     public void valueChanged(ListSelectionEvent e) { 
      if (!e.getValueIsAdjusting()) { 
       updateSelectedPathsFromSelectedRows(); 
      } 
     } 
    } 

:이 업데이트를 줄이기 위해 노력하고있다 JXTreeTable.java에서 일부 선의의 코드처럼 보인다. 프로젝트가 본질적으로 작동하지 않기 때문에 SwingX에 로컬 변경을해야합니다. :(