2016-07-17 11 views
1

私はデータをアルファベット順に並べ替えることができるようにJTableを拡張し、最初の文字に従ってセクションごとにデータを分けることができます。JTableを拡張した後にスクロールできませんか?

See this question and marked answer for more clarification

拡張テーブルが正常に動作します。しかし、ソートされたときに、テーブルのヘッダーをクリックすると、マウスホイールを使用してテーブルをスクロールするときに問題が発生します。 enter image description here

ここに拡張テーブルのコードを示します。 (注:上記のハイパーリンクでもこのコードを見つけることができます)。

import java.awt.BorderLayout; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.util.Map; 
import java.util.NavigableMap; 
import java.util.TreeMap; 
import javax.swing.JFrame; 
import javax.swing.JTable; 
import javax.swing.RowSorter; 
import javax.swing.SortOrder; 
import javax.swing.SwingConstants; 
import javax.swing.SwingUtilities; 
import javax.swing.event.RowSorterEvent; 
import javax.swing.event.TableModelEvent; 
import javax.swing.table.TableModel; 
import javax.swing.JScrollPane; 
import javax.swing.table.DefaultTableModel; 



public class SectionedTable 
     extends JTable { 

    private static final long serialVersionUID = 1; 

    private final NavigableMap<Integer, String> sectionHeadings 
      = new TreeMap<>(); 

    private final NavigableMap<Integer, Integer> rowTopEdges 
      = new TreeMap<>(); 

    // Used when calling SwingUtilities.layoutCompoundLabel. 
    private final Rectangle iconBounds = new Rectangle(); 
    private final Rectangle textBounds = new Rectangle(); 

    public SectionedTable() { 
     init(); 
    } 

    public SectionedTable(TableModel model) { 
     super(model); 
     init(); 
    } 

    private void init() { 
     setShowGrid(false); 
     setAutoCreateRowSorter(true); 

     recomputeSections(); 
     recomputeRowPositions(); 
    } 

    private void recomputeSections() { 
     if (sectionHeadings == null) { 
      return; 
     } 

     sectionHeadings.clear(); 

     RowSorter<? extends TableModel> sorter = getRowSorter(); 
     if (sorter == null) { 
      return; 
     } 

     for (RowSorter.SortKey key : sorter.getSortKeys()) { 
      SortOrder order = key.getSortOrder(); 
      if (order != SortOrder.UNSORTED) { 
       int sortColumn = key.getColumn(); 

       String lastSectionStart = ""; 
       int rowCount = getRowCount(); 
       for (int row = 0; row < rowCount; row++) { 
        System.out.println("row er : " + row); 
        System.out.println("rowcount er : " + rowCount); 
        System.out.println("sortColumn er : " + sortColumn); 
        Object value = getValueAt(row, sortColumn); 
        if (value == null) { 
         value = "?"; 
        } 

        String s = value.toString(); 
        if (s.isEmpty()) { 
         s = "?"; 
        } 

        String sectionStart = s.substring(0, 
          s.offsetByCodePoints(0, 1)); 
        sectionStart = sectionStart.toUpperCase(); 

        if (!sectionStart.equals(lastSectionStart)) { 
         sectionHeadings.put(row, sectionStart); 
         lastSectionStart = sectionStart; 
        } 
       } 
       break; 
      } 
     } 
    } 

    private void recomputeRowPositions() { 
     if (rowTopEdges == null) { 
      return; 
     } 

     rowTopEdges.clear(); 

     int y = getInsets().top; 
     int rowCount = getRowCount(); 
     int rowHeight = getRowHeight(); 
     for (int row = 0; row < rowCount; row++) { 
      rowTopEdges.put(y, row); 
      y += getRowHeight(row); 
      if (sectionHeadings.containsKey(row)) { 
       y += rowHeight; 
      } 
     } 
    } 

    @Override 
    public void tableChanged(TableModelEvent event) { 
     //super.tableChanged(event); 
     recomputeSections(); 
     recomputeRowPositions(); 
     super.tableChanged(event); 
    } 

    @Override 
    public void sorterChanged(RowSorterEvent event) { 
     recomputeSections(); 
     recomputeRowPositions(); 
     super.sorterChanged(event); 
    } 

    @Override 
    public void validate() { 
     super.validate(); 
     recomputeRowPositions(); 
    } 

    @Override 
    public int rowAtPoint(Point location) { 
     Map.Entry<Integer, Integer> entry = rowTopEdges.floorEntry(location.y); 
     if (entry != null) { 
      int row = entry.getValue(); 
      return row; 
     } 
     return -1; 
    } 

    @Override 
    public Rectangle getCellRect(int row, 
      int column, 
      boolean includeSpacing) { 

     Rectangle rect = super.getCellRect(row, column, includeSpacing); 

     int sectionHeadingsAbove = sectionHeadings.headMap(row, true).size(); 
     rect.y += sectionHeadingsAbove * getRowHeight(); 

     return rect; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     boolean ltr = getComponentOrientation().isLeftToRight(); 

     int rowHeight = getRowHeight(); 
     FontMetrics metrics = g.getFontMetrics(); 
     int ascent = metrics.getAscent(); 
     for (Map.Entry<Integer, String> entry : sectionHeadings.entrySet()) { 
      int row = entry.getKey(); 
      String heading = entry.getValue(); 

      Rectangle bounds = getCellRect(row, 0, true); 
      bounds.y -= rowHeight; 
      bounds.width = getWidth(); 
      bounds.grow(-6, 0); 

      iconBounds.setBounds(0, 0, 0, 0); 
      textBounds.setBounds(0, 0, 0, 0); 
      String text = SwingUtilities.layoutCompoundLabel(this, 
        metrics, heading, null, 
        SwingConstants.CENTER, SwingConstants.LEADING, 
        SwingConstants.CENTER, SwingConstants.CENTER, 
        bounds, iconBounds, textBounds, 0); 

      g.drawString(text, textBounds.x, textBounds.y + ascent); 

      int lineY = textBounds.y + ascent/2; 
      if (ltr) { 
       g.drawLine(textBounds.x + textBounds.width + 12, lineY, 
         getWidth() - getInsets().right - 12, lineY); 
      } else { 
       g.drawLine(textBounds.x - 12, lineY, 
         getInsets().left + 12, lineY); 
      } 
     } 
    } 

    public static void main(String[] args) { 

     DefaultTableModel model; 
     Object[][] data = new Object[50][5]; 
     String[] columnNames = {"First Name", 
      "Last Name", 
      "Sport", 
      "# of Years", 
      "Vegetarian"}; 

     for (int i = 0; i < 10; i++) { 
      for (int j = 0; j < 5; j++) { 
       data[i][j] = "Amy"; 
      } 
     } 

     for (int i = 10; i < 20; i++) { 
      for (int j = 0; j < 5; j++) { 
       data[i][j] = "Bob"; 
      } 
     } 

     for (int i = 20; i < 30; i++) { 
      for (int j = 0; j < 5; j++) { 
       data[i][j] = "Joe"; 
      } 
     } 

     for (int i = 30; i < 50; i++) { 
      for (int j = 0; j < 5; j++) { 
       data[i][j] = "M"; 
      } 
     } 

     SectionedTable table = new SectionedTable(); 
     model = new DefaultTableModel(data, columnNames); 
     table.setModel(model); 

     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       JTable table = new SectionedTable(); 
       table.setModel(model); 
       JScrollPane scrollPane = new JScrollPane(table); 
       frame.add(scrollPane, BorderLayout.CENTER); 
       frame.setSize(500, 500); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

私はこの問題を引き起こす可能性があります何かを見つけるのに苦労してきたと私はすべてのソリューションの近くにいませんよ。私はそれがrowAtPoint()またはgetCellRect()にあるかもしれないと思いますが、わかりません。誰かがこの問題がコード内にあるかもしれない場所を特定できますか?

+2

*「Xはうまく動作しますが」「* LOL!私はそのフレーズを聞いたたびに1ドルを欲しかった。 –

+0

@AndrewThompson私はあなたの大ファンです。 Swingセクションのあなたの答えの多くは、私を助けてくれました!私はあなたの問題を解決するためにあなたに挑戦します! – blueFalcon

+2

@blueFalcon、あなたがAndrew'sのファンであれば、質問を投稿するときに適切なMCVE/SSCCEを投稿する必要があることを知っておくべきです。それ以外の場合は、問題を解決するために必要な情報がありません。 – camickr

答えて

2

getScrollableUnitIncrement(...)メソッドがスクロールが機能しなくなったときに0を返していることに気付きました。私はあなたのテーブルに以下を追加迅速なハックとして

:それは他の問題を引き起こすかどう

@Override 
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) 
{ 
    int increment = super.getScrollableUnitIncrement(visibleRect, orientation, direction); 

    if (increment == 0) 
     increment = 16; 

    return increment; 
} 

は知ってはいけません。 これにより、0が返されたことがわかりました。したがって、スクロールは行われません。

関連する問題