Live sorting of JTable

前端 未结 4 1865
离开以前
离开以前 2020-12-28 23:14

I\'ve figured out how to get a JTable to be sorted properly, but I can\'t figure out how to get it to automatically update the sort order when a table cell is c

4条回答
  •  感动是毒
    2020-12-28 23:43

    Its a long-standing bug on JTable, reported in 2007 (astonished that it isn't fixed, not even in jdk7)

    Firing a update on all rows is a reasonable quick fix if it doesn't degrade performance too much (due to triggering frequent complete resorts). For the fearless, here's a partial fix on JTable - partial, because not yet all possible scenarios are captured. Which is the reason it never made it into JXTable (or maybe I had other priorities then :-)

    public static class JTableRepaintOnUpdate extends JTable {
    
      private UpdateHandler beforeSort;
    
      @Override
      public void sorterChanged(RowSorterEvent e) {
          super.sorterChanged(e);
          maybeRepaintOnSorterChanged(e);
      } 
    
      private void beforeUpdate(TableModelEvent e) {
          if (!isSorted()) return;
          beforeSort = new UpdateHandler(e);
      }
    
      private void afterUpdate() {
          beforeSort = null;
      }
    
      private void maybeRepaintOnSorterChanged(RowSorterEvent e) {
          if (beforeSort == null) return;
          if ((e == null) || (e.getType() != RowSorterEvent.Type.SORTED)) return;
          UpdateHandler afterSort = new UpdateHandler(beforeSort);
          if (afterSort.allHidden(beforeSort)) {
              return;
          } else if (afterSort.complex(beforeSort)) {
              repaint();
              return;
          }
          int firstRow = afterSort.getFirstCombined(beforeSort);
          int lastRow = afterSort.getLastCombined(beforeSort);
          Rectangle first = getCellRect(firstRow, 0, false);
          first.width = getWidth();
          Rectangle last = getCellRect(lastRow, 0, false);
          repaint(first.union(last));
      }
    
      private class UpdateHandler {
          private int firstModelRow;
          private int lastModelRow;
          private int viewRow;
          private boolean allHidden;
    
          public UpdateHandler(TableModelEvent e) {
              firstModelRow = e.getFirstRow();
              lastModelRow = e.getLastRow();
              convert();
          }
    
          public UpdateHandler(UpdateHandler e) {
              firstModelRow = e.firstModelRow;
              lastModelRow = e.lastModelRow;
              convert();
          }
    
          public boolean allHidden(UpdateHandler e) {
              return this.allHidden && e.allHidden;
          }
    
          public boolean complex(UpdateHandler e) {
              return (firstModelRow != lastModelRow);
          }
    
          public int getFirstCombined(UpdateHandler e) {
              if (allHidden) return e.viewRow;
              if (e.allHidden) return viewRow;
              return Math.min(viewRow, e.viewRow);
          }
    
          public int getLastCombined(UpdateHandler e) {
              if (allHidden || e.allHidden) return getRowCount() - 1;
              return Math.max(viewRow, e.viewRow);
    
          }
    
          private void convert() {
              // multiple updates
              if (firstModelRow != lastModelRow) {
                  // don't bother too much - calculation not guaranteed to do anything good
                  // just check if the all changed indices are hidden
                  allHidden = true;
                  for (int i = firstModelRow; i <= lastModelRow; i++) {
                      if (convertRowIndexToView(i) >= 0) {
                          allHidden = false;
                          break;
                      }
                  }
                  viewRow = -1;
                  return;
              }
              // single update
              viewRow = convertRowIndexToView(firstModelRow);
              allHidden = viewRow < 0;
          }
    
      }
    
      private boolean isSorted() {
          // JW: not good enough - need a way to decide if there are any sortkeys which
          // constitute a sort or any effective filters  
          return getRowSorter() != null;
      }
    
      @Override
      public void tableChanged(TableModelEvent e) {
          if (isUpdate(e)) {
              beforeUpdate(e);
          }
          try {
              super.tableChanged(e);
          } finally {
              afterUpdate();
          }
      }
    
      /**
       * Convenience method to detect dataChanged table event type.
       * 
       * @param e the event to examine. 
       * @return true if the event is of type dataChanged, false else.
       */
      protected boolean isDataChanged(TableModelEvent e) {
          if (e == null) return false;
          return e.getType() == TableModelEvent.UPDATE && 
              e.getFirstRow() == 0 &&
              e.getLastRow() == Integer.MAX_VALUE;
      }
    
      /**
       * Convenience method to detect update table event type.
       * 
       * @param e the event to examine. 
       * @return true if the event is of type update and not dataChanged, false else.
       */
      protected boolean isUpdate(TableModelEvent e) {
          if (isStructureChanged(e)) return false;
          return e.getType() == TableModelEvent.UPDATE && 
              e.getLastRow() < Integer.MAX_VALUE;
      }
    
      /**
       * Convenience method to detect a structureChanged table event type.
       * @param e the event to examine.
       * @return true if the event is of type structureChanged or null, false else.
       */
      protected boolean isStructureChanged(TableModelEvent e) {
          return e == null || e.getFirstRow() == TableModelEvent.HEADER_ROW;
      }
    
    }
    

提交回复
热议问题