2011-06-20 3 views
7

cómo es posible sincronizarlas texto tecleado en JTextField (entonces por DocumentListener pasado String a la RowFilter) con TableCell si contiene mismo como valor de cadena en JTextField/Documento,Highlights subCadena en el TableCell (s) que está utilizando para JTable filetering

y luego destacados (es decir Fe cambio texto Color.Red) para el texto idéntico en sincronizada TableCell(s)

sé que por el uso de algunos hacks es que sea posible mediante el uso de

1/mediante el uso de getTableCellRendererComponent

2/utilizando prepareRenderer

¿Hay otra y tal manera (s) correcta

poco código modificado de JTable tutorial

import java.awt.*; 
import java.util.regex.PatternSyntaxException; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.table.*; 

public class TableFilterSorter extends JPanel { 

    private boolean DEBUG = false; 
    private static final long serialVersionUID = 1L; 

    public TableFilterSorter() { 
     super(new BorderLayout(5, 5)); 
     final JTextField filterCpText = new JTextField(); 
     filterCpText.setFont(new Font("Serif", Font.BOLD, 28)); 
     filterCpText.setForeground(Color.BLUE); 
     filterCpText.setBackground(Color.LIGHT_GRAY); 
     JPanel filterCpPanel = new JPanel(); 
     filterCpPanel.setLayout(new BorderLayout(5, 5)); 
     filterCpPanel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); 
     filterCpPanel.setBackground(Color.LIGHT_GRAY); 
     filterCpPanel.setPreferredSize(new Dimension(300, 30)); 
     filterCpPanel.add(filterCpText, BorderLayout.CENTER); 
     add(filterCpPanel, BorderLayout.NORTH); 
     final JTable table = new JTable(new MyTableModel()); 
     table.setPreferredScrollableViewportSize(new Dimension(500, 160)); 
     table.setFillsViewportHeight(true); 
     JScrollPane scrollPane = new JScrollPane(table); 
     add(scrollPane, BorderLayout.CENTER); 
     TableModel myTableModel = table.getModel(); 
     final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(myTableModel); 
     table.setRowSorter(sorter); 
     filterCpText.getDocument().addDocumentListener(new DocumentListener() { 

      private void searchFieldChangedUpdate(DocumentEvent evt) { 
       String text = filterCpText.getText(); 
       if (text.length() == 0) { 
        sorter.setRowFilter(null); 
        table.clearSelection(); 
       } else { 
        try { 
         sorter.setRowFilter(RowFilter.regexFilter("(?i)" + text, 4)); 
         table.clearSelection(); 
        } catch (PatternSyntaxException pse) { 
         JOptionPane.showMessageDialog(null, "Bad regex pattern", 
           "Bad regex pattern", JOptionPane.ERROR_MESSAGE); 
        } 
       } 
      } 

      @Override 
      public void insertUpdate(DocumentEvent evt) { 
       searchFieldChangedUpdate(evt); 
      } 

      @Override 
      public void removeUpdate(DocumentEvent evt) { 
       searchFieldChangedUpdate(evt); 
      } 

      @Override 
      public void changedUpdate(DocumentEvent evt) { 
       searchFieldChangedUpdate(evt); 
      } 
     }); 
    } 

    private class MyTableModel extends AbstractTableModel { 

     private static final long serialVersionUID = 1L; 
     private String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"}; 
     private Object[][] data = { 
      {"Mary", "Campione", "Snowboarding", new Integer(5), false}, 
      {"Alison", "Huml", "Rowing", new Integer(3), true}, 
      {"Kathy", "Walrath", "Knitting", new Integer(2), false}, 
      {"Sharon", "Zakhour", "Speed reading", new Integer(20), true}, 
      {"Philip", "Milne", "Pool", new Integer(10), false}, 
      {"Mary", "Campione", "Snowboarding", new Integer(5), false}, 
      {"Alison", "Huml", "Rowing", new Integer(3), true}, 
      {"Kathy", "Walrath", "Knitting", new Integer(2), false}, 
      {"Sharon", "Zakhour", "Speed reading", new Integer(20), true}, 
      {"Philip", "Milne", "Pool", new Integer(10), false},}; 

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

     @Override 
     public int getRowCount() { 
      return data.length; 
     } 

     @Override 
     public String getColumnName(int col) { 
      return columnNames[col]; 
     } 

     @Override 
     public Object getValueAt(int row, int col) { 
      return data[row][col]; 
     } 

     @Override 
     public Class<?> getColumnClass(int c) { 
      return getValueAt(0, c).getClass(); 
     } 

     @Override 
     public boolean isCellEditable(int row, int col) { 
      if (col < 2) { 
       return false; 
      } else { 
       return true; 
      } 
     } 

     @Override 
     public void setValueAt(Object value, int row, int col) { 
      if (DEBUG) { 
       System.out.println("Setting value at " + row + "," + col 
         + " to " + value + " (an instance of " + value.getClass() + ")"); 
      } 
      data[row][col] = value; 
      fireTableCellUpdated(row, col); 
      if (DEBUG) { 
       System.out.println("New value of data:"); 
       printDebugData(); 
      } 
     } 

     private void printDebugData() { 
      int numRows = getRowCount(); 
      int numCols = getColumnCount(); 
      for (int i = 0; i < numRows; i++) { 
       System.out.print(" row " + i + ":"); 
       for (int j = 0; j < numCols; j++) { 
        System.out.print(" " + data[i][j]); 
       } 
       System.out.println(); 
      } 
      System.out.println("--------------------------"); 
     } 
    } 

    private static void createAndShowGUI() { 
     JFrame frame = new JFrame("TableDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     TableFilterSorter newContentPane = new TableFilterSorter(); 
     newContentPane.setOpaque(true); 
     frame.setContentPane(newContentPane); 
     frame.setLocation(150, 150); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 

Respuesta

7

JXTable puede hacer entonces a través de un Resaltador - vea las demostraciones de swinglabs para un ejemplo (MatchingTextHighlighter en la demostración de búsqueda) - hay un resaltado de fondo aplicado por un Pintor.

Puede hacer algo así manualmente en algún lugar de su procesador. Si usa JLabel como renderingComponent, básicamente tiene que encontrar partes del texto que necesiten resaltar el fondo y pintar el fondo para esa región (a continuación se muestra un fragmento de código para encontrar las áreas, c & p del ejemplo de demos). Alternativamente, usted puede considerar el uso de un JTextField como componente de representación: el adv es que Highlighter (de javax.swing.text) está integrado en el disadv son los problemas habituales con composiciones de texto como de extracción de grasas ;-)

/** 
* Finds the rectangles that contain rendered characters that match the 
* pattern. 
* 
* @param object an optional configuration parameter. This may be null. 
* @param width width of the area to paint. 
* @param height height of the area to paint. 
* @return a <code>List</code> of <code>Rectangle</code>s marking characters 
*   to highlight 
*/ 
protected List<Rectangle> findHighlightAreas(JLabel object, int width, 
     int height) { 
    String text = object.getText(); 

    insets = object.getInsets(insets); 

    viewR.x = 0 + insets.left; 
    viewR.y = 0 + insets.bottom; 
    viewR.width = width - insets.right; 
    viewR.height = height - insets.top; 

    // Reset the text and view rectangle x any y coordinates. 
    // These are not set to 0 in SwingUtilities.layoutCompoundLabel 
    iconR.x = iconR.y = 0; 
    textR.x = textR.y = 0; 

    FontMetrics fm = object.getFontMetrics(object.getFont()); 
    String clippedText = SwingUtilities.layoutCompoundLabel(object, fm, 
      text, object.getIcon(), object.getVerticalAlignment(), object 
        .getHorizontalAlignment(), object 
        .getVerticalTextPosition(), object 
        .getHorizontalTextPosition(), viewR, iconR, textR, 
      object.getIconTextGap()); 

    int xOffset = calculateXOffset(object, viewR, textR); 

    String textToSearch = clippedText; 
    // Check to see if the text will be clipped 
    if (!object.getText().equals(clippedText)) { 
     // TODO There has to be a better way that assuming ellipses 
     // are the last characters of the text 
     textToSearch = clippedText.substring(0, clippedText.length() - 3); 
    } 

    return createHighlightAreas(textToSearch, fm, xOffset, height); 
} 

/** 
* Creates the rectangles that contain matched characters in the given text. 
* 
* @param text the text to search 
* @param fm the font metrics of the rendered font 
* @param xOffset the x offset at which text rendering starts 
* @param height the height of painted highlights 
* @return a <code>List</code> of highlight areas to paint 
*/ 
protected List<Rectangle> createHighlightAreas(String text, FontMetrics fm, 
     int xOffset, int height) { 
    SearchPredicate predicate = (SearchPredicate) getHighlightPredicate(); 
    Matcher matcher = predicate.getPattern().matcher(text); 

    List<Rectangle> highlightAreas = null; 
    int startFrom = 0; 
    while (startFrom < text.length() && matcher.find(startFrom)) { 
     if (highlightAreas == null) { 
      highlightAreas = new ArrayList<Rectangle>(); 
     } 

     int start = matcher.start(); 
     int end = matcher.end(); 

     if (start == end) { 
      // empty matcher will cause infinite loop 
      break; 
     } 

     startFrom = end; 

     int highlightx; 
     int highlightWidth; 

     if (start == 0) { 
      // start highlight from the start of the field 
      highlightx = textR.x + xOffset; 
     } else { 
      // Calculate the width of the unhighlighted text to 
      // get the start of the highlighted region. 
      String strToStart = text.substring(0, start); 
      highlightx = textR.x + fm.stringWidth(strToStart) + xOffset; 
     } 

     // Get the width of the highlighted region 
     String highlightText = text.substring(start, end); 
     highlightWidth = fm.stringWidth(highlightText); 

     highlightAreas.add(new Rectangle(highlightx, 0, highlightWidth, 
       height)); 
    } 

    if (highlightAreas == null) { 
     highlightAreas = Collections.emptyList(); 
    } else { 
     coalesceHighlightAreas(highlightAreas); 
    } 
    return highlightAreas; 
} 

/** 
* Joins highlight rectangles that mark adjacent horizontal areas into 
* single rectangles. This is useful to renderers that vary horizontally, 
* such a horizontal gradient - the gradient will not restart when there are 
* two adjacent highlight areas. 
* 
* @param highlightAreas a <code>List</code> of <code>Rectangle</code>s. 
*/ 
protected void coalesceHighlightAreas(List<Rectangle> highlightAreas) { 
    Collections.sort(highlightAreas, X_AXIS_RECTANGLE_COMPARATOR); 

    int i = 0; 
    while (i < highlightAreas.size() - 1) { 
     Rectangle r1 = highlightAreas.get(i); 
     Rectangle r2 = highlightAreas.get(i + 1); 

     if (r1.x + r1.width == r2.x) { 
      r1.width += r2.width; 
      highlightAreas.remove(i + 1); 
     } else { 
      i++; 
     } 
    } 
} 

/** 
* Calculates the x offset of highlights based on component orientation and 
* text direction. 
* 
* @param component the renderer component 
* @param viewR the view rectangle of the renderer component 
* @param textR the text rectangle of the renderer component 
* @return the number of pixels to offset the highlight from the left edge 
*   of the component 
*/ 
protected int calculateXOffset(JLabel component, Rectangle viewR, 
     Rectangle textR) { 
    int horizAlignment = component.getHorizontalAlignment(); 
    boolean leftToRight = component.getComponentOrientation() 
      .isLeftToRight(); 

    if (horizAlignment == SwingConstants.LEFT 
      || (horizAlignment == SwingConstants.LEADING && leftToRight) 
      || (horizAlignment == SwingConstants.TRAILING && !leftToRight)) { 
     return 0; 
    } else if (horizAlignment == SwingConstants.RIGHT 
      || (horizAlignment == SwingConstants.TRAILING && !leftToRight) 
      || (horizAlignment == SwingConstants.LEADING && leftToRight)) { 
     return viewR.width - textR.width; 
    } else if (horizAlignment == SwingConstants.CENTER) { 
     return (viewR.width - textR.width)/2; 
    } 
    throw new AssertionError("Unknown horizonal alignment " 
      + horizAlignment); 
} 
+0

que debe ser posible en la norma API java6, de verdad gracias – mKorbel

3

inspirado en respuesta kleopatra', he intentado todo lo que es posible o saber, ahora el resultado es que su ejemplo me invocando Pattern

enter image description here

parece a patrones es quickiest, más de lo que esperaba, este código se perdió algo de RowSorter, va sobre la idea de cómo hacerlo, con salida rápida a la GUI,

import java.awt.*; 
import java.util.Vector; 
import java.util.regex.Pattern; 
import javax.swing.*; 
import javax.swing.table.*; 

public class HiglightNumberValueInTableCell { 

    private String testS; 
    private JFrame frame = new JFrame("frameTitle"); 
    private JScrollPane tblS = new JScrollPane(); 
    private JTable tbl; 
    private Vector<String> rOrH; 
    private long t1 = 0L; 
    private long t2 = 0L; 

    public HiglightNumberValueInTableCell() { 
     t1 = System.currentTimeMillis(); 
     int regLenght = 25000; 
     int chars = 0; 
     AlphaChars aChars = new AlphaChars(); 
     testS = aChars.getNext(regLenght); 
     rOrH = new Vector<String>(); 
     Vector<Vector<String>> rowD = new Vector<Vector<String>>(); 
     for (int e = 0; e < regLenght;) { 
      chars++; 
      //if (chars > 50) { //one char in table cell 
      if (chars > 20) { 
       chars = 1; 
       rowD.add(rOrH); 
       rOrH = new Vector<String>(); 
      } 
      //String str = (testS.substring(e, (e + 1))).toString();//one char in table cell 
      String str = (testS.substring(e, (e + 5))).toString(); 
      if (str != null) { 
       rOrH.add(str); 
      } else { 
       rOrH.add(""); 
      } 
      //e++;//one char in table cell 
      e += 5; 
     } 
     rOrH = new Vector<String>(); 
     //for (int i = 0; i < 50; i++) {//one char in table cell 
     for (int i = 0; i < 20; i++) { 
      rOrH.add(String.valueOf(i + 1)); 
     } 
     tbl = new JTable(rowD, rOrH); 
     tblS = new JScrollPane(tbl, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, 
       ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
     tblS.setPreferredSize(new Dimension(1000, 403)); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(tblS, BorderLayout.CENTER); 
     frame.setLocation(50, 50); 
     frame.pack(); 
     addColumnRenderes(); 
    } 

    private void addColumnRenderes() { 
     for (int i = 0; i < tbl.getColumnCount(); i++) { 
      RowColorRenderer rowRenderer = new RowColorRenderer(i); 
      TableColumn column = tbl.getColumnModel().getColumn(i); 
      column.setCellRenderer(rowRenderer); 
     } 
     Runnable doRun = new Runnable() { 

      @Override 
      public void run() { 
       showFrame(); 
      } 
     }; 
     SwingUtilities.invokeLater(doRun); 
    } 

    private void showFrame() { 
     Runnable doRun = new Runnable() { 

      @Override 
      public void run() { 
       frame.setVisible(true); 
       t2 = System.currentTimeMillis(); 
       System.out.println("miliSec:" + (t2 - t1)); //aver. 45 miliSec. 
      } 
     }; 
     SwingUtilities.invokeLater(doRun); 
    } 

    private class RowColorRenderer extends DefaultTableCellRenderer { 

     private static final long serialVersionUID = 1L; 
     private int colNo = 0; 

     RowColorRenderer(int col) { 
      colNo = col; 
     } 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, 
       boolean isSelected, boolean hasFocus, int row, int column) { 
      Component comp = super.getTableCellRendererComponent(table, value, 
        isSelected, hasFocus, row, column); 
      JComponent jc = (JComponent) comp; 
      if (!isSelected) { 
       if (table.getValueAt(row, colNo) != null) { 
        String str = table.getValueAt(row, colNo).toString(); 
        if (!str.isEmpty()) { 
         if (Pattern.compile("\\d").matcher(str).find()) { 
          if (((Pattern.compile("[02468]").matcher(str).find())) 
            && (!(Pattern.compile("[13579]").matcher(str).find()))) { 
           setForeground(Color.magenta); 
           setBackground(Color.orange); 
          } else if ((!(Pattern.compile("[02468]").matcher(str).find())) 
            && ((Pattern.compile("[13579]").matcher(str).find()))) { 
           setForeground(Color.blue); 
           setBackground(Color.yellow); 
          } else if (((Pattern.compile("[02468]").matcher(str).find())) 
            && ((Pattern.compile("[13579]").matcher(str).find()))) { 
           setForeground(Color.red); 
           setBackground(Color.cyan); 
          } 
          setFont(new Font("Serif", Font.BOLD, 12)); 
          setHorizontalAlignment(CENTER); 
         } else { 
          setBackground(table.getBackground()); 
          setForeground(table.getForeground()); 
          setFont(new Font("Serif", Font.PLAIN, 8)); 
          setHorizontalAlignment(CENTER); 
         } 
        } 
       } 
      } 
      return this; 
     } 
    } 

    private class AlphaChars { 

     public static final int MIN_LENGTH = 2000; 
     private java.util.Random rand = new java.util.Random(); 
     private char[] AlphaChars = { 
      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 
      'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 
      'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 
      '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', '*', '/', '<', '>', '&', 
      '#', '@', '{', '}', '?', ':', '_', '"', '!', ')', '('}; 

     public String getNext() { 
      StringBuilder strbuf = new StringBuilder(); 
      for (int i = 0; i < MIN_LENGTH; i++) { 
       strbuf.append(getAlphaChars()[getRand().nextInt(getAlphaChars().length)]); 
      } 
      return strbuf.toString(); 
     } 

     public String getNext(int reqLenght) { 
      StringBuilder strbuf = new StringBuilder(); 
      for (int i = 0; i < reqLenght; i++) { 
       strbuf.append(getAlphaChars()[getRand().nextInt(getAlphaChars().length)]); 
      } 
      return strbuf.toString(); 
     } 

     public java.util.Random getRand() { 
      return rand; 
     } 

     public void setRand(java.util.Random aRand) { 
      rand = aRand; 
     } 

     public char[] getAlphaChars() { 
      return AlphaChars; 
     } 

     public void setAlphaChars(char[] aAlphaChars) { 
      AlphaChars = aAlphaChars; 
     } 
    } 

    public static void main(String args[]) { 
     HiglightNumberValueInTableCell hnvit = new HiglightNumberValueInTableCell(); 
    } 
} 
+0

1 Este ejemplo pone de relieve el beneficio de la velocidad de extracción de grasas 'JTable', que utilizan la [flyweight] (http://en.wikipedia.org/ wiki/Flyweight_pattern). – trashgod

Cuestiones relacionadas