突出表格单元格中的subString,用于JTable过滤

时间:2011-06-20 12:06:01

标签: java swing jtable highlighting rowfilter

如果包含JTextField(如果DocumentListener传递String RowFilter TableCellColor.Red同步,如果包含{String}值,则如何将文本同步到TableCell(s)在JTextField / Document中,

然后突出显示(意思是f.e.更改文本getTableCellRendererComponent)同步prepareRenderer中的相同文字

我知道通过使用

可以使用一些黑客

1 /使用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(); } }); } }

2 /使用{{1}}

是否存在另一种可能正确的方式

来自JTable教程的一点点修改代码

{{1}}

2 个答案:

答案 0 :(得分:7)

JXTable可以通过荧光笔实现 - 请参阅swinglabs-demos示例(搜索演示中的MatchingTextHighlighter) - 画家应用背景突出显示。

您可以在渲染器中的某个位置手动执行此类操作。如果使用JLabel作为renderingComponent,您基本上必须找到需要背景突出显示的部分文本并绘制​​该区域的背景(下面是用于查找区域的代码片段,演示示例中的c&amp; p)。或者你可以考虑使用JTextField作为渲染组件:adv是Highlighter(来自javax.swing.text)是内置的,disadv是文本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);
}

答案 1 :(得分:3)

受到kleopatra'回复的启发,我尝试了所有可能或知道的事情,现在结果是她的例子引用了我Pattern

enter image description here

看起来像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();
    }
}