突出显示用于JTable文件筛选的TableCell中的subString

如果在JTextField / Document中包含与String值相同的文本,那么如何使用TableCell将文本types化成JTextField (然后通过将DocumentListener传递给RowFilter

然后为同步的TableCell(s)相同文本加Color.Red (意思是改变文本Color.Red TableCell(s)

我知道通过使用一些黑客的使用是可能的

1 /通过使用getTableCellRendererComponent

2 /通过使用prepareRenderer

有没有另一种,也许正确的方法(S)

从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<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(); } }); } } 

JXTable可以通过荧光笔(Highlighter)来实现,例如在示例中使用的是Swinglabs-demos(在search演示中使用MatchingTextHighlighter) – Painter会应用背景亮点。

你可以在渲染器的某个地方手动做这样的事情。 如果使用JLabel作为renderingComponent,则基本上必须find需要背景突出显示的部分文本,并绘制该区域的背景(以下是查找区域的代码片段,演示示例中的c&p)。 或者,您可以考虑使用JTextField作为渲染组件:adv是Highlighter(来自javax.swing.text)是内置的,劣势是文本comps作为渲染器的常见问题;-)

 /** * 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); } 

灵感来自kleopatra的回复,我尝试了一切可能或知道的事情,现在的结果是她的榜样调用了我的Pattern

在这里输入图像描述

看起来像Pattern是最快的,超出了我的预期,这段代码错过了RowSorter的一些东西,它想知道如何做到这一点,快速输出到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(); } }