Evidenzia sottostringa nelle TableCell che si stanno utilizzando per il filtraggio JTable

come è ansible sincronizzare il testo digitato in JTextField (quindi da DocumentListener passato String al RowFilter ) con TableCell se contiene lo stesso valore String in JTextField / Document,

e poi evidenzia (per esempio cambia il testo Color.Red ) per il testo identico in TableCell(s) sincronizzati

So che l’utilizzo di alcuni hack è ansible utilizzando

1 / utilizzando getTableCellRendererComponent

2 / usando prepareRenderer

c’è un altro e forse modo corretto (s)

codice leggermente modificato dal tutorial di JTable

 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 sorter = new TableRowSorter(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(); } }); } } 

JXTable può farlo tramite un Evidenziatore: per visualizzare un esempio di dimostrazioni di swinglabs (MatchingTextHighlighter nella demo di ricerca), un pittore appoggia un evidenziatore sullo sfondo.

Puoi fare qualcosa del genere manualmente da qualche parte nel tuo renderer. Se si utilizza una JLabel come renderingComponent, è fondamentalmente necessario trovare parti del testo che necessitano dell’evidenziazione dello sfondo e dipingere lo sfondo per quella regione (di seguito è riportato uno snippet di codice per trovare le aree, c & p dall’esempio demo). In alternativa si potrebbe considerare l’utilizzo di un JTextField come componente di rendering: l’adv è che Highlighter (da javax.swing.text) è integrato, il disadv sono i soliti problemi con i comp del testo come renderer 😉

 /** * 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 List of Rectangles marking characters * to highlight */ protected List 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 List of highlight areas to paint */ protected List createHighlightAreas(String text, FontMetrics fm, int xOffset, int height) { SearchPredicate predicate = (SearchPredicate) getHighlightPredicate(); Matcher matcher = predicate.getPattern().matcher(text); List highlightAreas = null; int startFrom = 0; while (startFrom < text.length() && matcher.find(startFrom)) { if (highlightAreas == null) { highlightAreas = new ArrayList(); } 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 List of Rectangles. */ protected void coalesceHighlightAreas(List 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); } 

ispirato alla risposta di kleopatra, ho provato tutto ciò che è ansible o noto, ora il risultato è che il suo esempio mi ha chiamato Pattern

inserisci la descrizione dell'immagine qui

sembra che Pattern sia il più veloce, più di quanto mi aspettassi, questo codice ha mancato qualcosa su RowSorter, ha idea di come farlo, con un output veloce per 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 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(); Vector> rowD = new Vector>(); 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 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(); //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(); } }