1

The following code will get text from a textfield and searches it in a JTable. It shows only the first occurence of the text. I need successive occurence too. So, please guide me how to achieve this. Thanks in advance.

private void search8()
{
    String target8 = sear8.getText();
    for(int row = 0; row < table8.getRowCount(); row++)
        for(int col = 0; col < table8.getColumnCount(); col++)
        {
            String next8 = (String)table8.getValueAt(row, col);
            if(next8.equals(target8))
            {
                showSearchResults(row, col);
                return;
            }
        }
}

Updated:

private void showSearchResults(int row, int col)
{
    CustomRenderer renderer = (CustomRenderer)table8.getCellRenderer(row, col);
    renderer.setTargetCell(row, col);
    Rectangle r8 = table8.getCellRect(row, col, false);
    table8.scrollRectToVisible(r8);
    table8.repaint();
}

class CustomRenderer implements TableCellRenderer
{
    public CustomRenderer()
    {
       label = new JLabel();
       label.setHorizontalAlignment(JLabel.CENTER);
       label.setOpaque(true);
       targetRow = -1;
       targetCol = -1;
    }

    public Component getTableCellRendererComponent(JTable table,
    Object value,boolean isSelected,boolean hasFocus,int row, int column)
    {
       if(isSelected)
       {
           label.setBackground(table.getSelectionBackground());
           label.setForeground(table.getSelectionForeground());
       }
       else
       {
           label.setBackground(table.getBackground());
           label.setForeground(table.getForeground());
       }
       if(row == targetRow && column == targetCol)
       {
           label.setBackground(new Color(176,196,222));
           //label.setBorder(BorderFactory.createLineBorder(Color.red));
           label.setFont(table.getFont().deriveFont(Font.BOLD));
       }
       else
       {
           label.setBorder(null);
           label.setFont(table.getFont());
       }
       label.setText((String)value);
       return label;
    }

    public void setTargetCell(int row, int col)
    {
       targetRow = row;
       targetCol = col;
    }
} 
Gomathi
  • 973
  • 7
  • 17
  • 37
  • How do you mean "successive occurrence"? Do you want to have only one instance at a time highlighted and require the user to have select "next", or do you want to display all of them at the same time? – MadProgrammer Jul 27 '12 at 13:25
  • @MadProgrammer User has to select next – Gomathi Jul 27 '12 at 14:03
  • @MadProgrammer Both are ok for me Sir. – Gomathi Jul 27 '12 at 14:14
  • @MadProgrammer I tried storing values using an array, Sir. I have updated that code in the question. But I get Array Index out of bounds exception. What mistake I'd have done,Sir? – Gomathi Jul 27 '12 at 15:03
  • @Sujay thanks for cleaning up the formatting mess :-) To OP: this site has problem with formatting code containing tabs (or even worse: a mixture of tabs and spaces) for indentation, so please don't use tabs at all. – kleopatra Jul 27 '12 at 15:28
  • @kleopatra - It also helps me read the code as well and help out the OP :) – Sujay Jul 27 '12 at 15:30

3 Answers3

3

You return immediately after you find the first match for target8.

Better to build up a List of matching Strings and pass to your method showSearchResults.

Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • I tried storing values using an array, Sir. I have updated that code in the question. But I get Array Index out of bounds exception. What mistake I'd have done,Sir?I'm a beginner. – Gomathi Jul 27 '12 at 15:02
3

There are two ways to achieve this:

  • As Reimeus suggested, perform a single parse to find all the occurence of the particular search keyword(s) and store their position in a list. And then call your showSearchResults() and iterate through the list.

  • The second option is to store your last scanned location at some place. And then when the user presses next, start your search from this position, instead of (0,0) again.

I would personally prefer the first option because I do not have to scan this table repeatedly. Also this list will help me implement something like "previous" and "next" functionality quite easily

Edit: This is one way of how you can achieve this (note that you've to customize it based on your requirement, this is just to help you get started):

private void search8() {
    ArrayList<String> resultList = new ArrayList<String>();

    String target8 = sear8.getText();
    for (int row = 0; row < table8.getRowCount(); row++) {
        for (int col = 0; col < table8.getColumnCount(); col++) {
            String next8 = (String) table8.getValueAt(row, col);
            if (next8.contains(target8)) {
                resultList.add(row + "," + col);
            }
        }
    }

    System.out.println(sarr8.length);

    String[] tokens;
    for (String result : resultList) {
        try {
            tokens = result.split("[,]");
            showSearchResults(tokens[0], tokens[1]);
        } finally {
            tokens = null;
        }
    }

    /**
     * Your remaining part
     */
}
Sujay
  • 6,753
  • 2
  • 30
  • 49
  • I tried storing values using an array, Sir. I have updated that code in the question. But I get Array Index out of bounds exception. What mistake I'd have done,Sir?I'm a beginner. – Gomathi Jul 27 '12 at 15:02
1
// I'd, personally, make this protected as you may wish to change the how the search 
// is performed in the future.
protected void search8() {

    // You've assumed that there are only ever 40 elements
    // while you've allowed for a variable number of search positions
    // You would need (at least) (rowCount * colCount) * 2 elements to be
    // safe.  This is a little ridiculous considering that there might
    // only be 1 reuslt in the table
    // int[] sarr8 = new int[40]; <-- Don't really want to do this

    // Instead, we should use a dynamic array instead
    // The ArrayList is a Collection implementation backed by an array
    // but it has the means to grow (and shrink) to meet the capacity requirements
    List<Point> slist8 = new ArrayList<Point>(25); // <-- you could change the initial value as you see fit
    int i = 0;
    String target8 = sear8.getText();
    for (int row = 0; row < table8.getRowCount(); row++) {
        for (int col = 0; col < table8.getColumnCount(); col++) {
            String next8 = (String) table8.getValueAt(row, col);
            if (next8.contains(target8)) {
                // Okay, this kinda cheating, but we want to store col/row or x/y
                // cell coordinates.  You could make your own class "Cell" class,
                // but for what we want, this is exactly the same
                Point cell = new Point(col. row);
                //sarr8[i] = row;
                //sarr8[i + 1] = col;
                //i = i + 2;
                slist8.add(cell);
            }
        }
    }

    //System.out.println(sarr8.length);
    System.out.println(slist8.size());

    //for (int j = 0; j < sarr8.length; j += 2) {
    //    showSearchResults(sarr8[j], sarr8[j + 1]);
    //    return;
    //}

    // Now, personally, I'd pass in the whole result set to the "showSearchResults"
    // method, because, IMHO, that's the methods domain of responsibility, ours was
    // to simply find the results.

    showSearchResults(slist8);

    // At this point, the showSearchResults method can determine how it wants to display
    // the search results

}

This approach was also demonstrated by @Sujay in his answer

UPDATED

for (Point p : slist8) {
    showSearchResults(p.x, p.y);
}

else

private void showSearchResults(List<Point> results)
{

    for (Point p : results) 
    {
        int col = p.x;
        int row = p.y;
        CustomRenderer renderer = (CustomRenderer)table8.getCellRenderer(row, col);
        renderer.setTargetCell(row, col);
        Rectangle r8 = table8.getCellRect(row, col, false);
        table8.scrollRectToVisible(r8);
    }
    table8.repaint();
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • That was a great explanation, Sir! Thank you so much. But, I have a doubt. I have updated my showSearchResults method. It accepts two inputs row and column. If we send a list of points, how to divide it in the function,Sir? Sorry, if I'm asking silly question Sir. – Gomathi Jul 28 '12 at 05:14
  • Sorry, Point has two properties, x & y. If you don't want to pass the Point objects themselves, you could store an int array (int[]) in the list instead – MadProgrammer Jul 28 '12 at 05:20
  • Considering that I pass them as points, how should I split it up in the function Sir? Or else modify? – Gomathi Jul 28 '12 at 05:24
  • Thank you so much, Sir. When I run it, all gets highlighted fast and it vanishes.Only the final occurence gets highlighted. Why sir? What mistake I'd have done for not highlighting every occurence? I guess I must have done mistake in CustomRenderer. Am I right, Sir? – Gomathi Jul 28 '12 at 05:41
  • I had a line `table8.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);` .I commented it out. But, no use. – Gomathi Jul 28 '12 at 05:44
  • Cell renderers are "stamps", the table uses a single copy of the renderer to render all the cells in the table. The problem is,your cell renderer only allows for a single match at a time, which is fine, but we've not discussed how you might implement a next/prev search model. Either you need to devise a next/previous search model or change your renderer to support more then one result at time. Now before you ask, how do you think it could be achieved? – MadProgrammer Jul 28 '12 at 06:01
  • `Using a renderer to display multiple cells drastically reduces the storage requirements for a large table.` in [http://java.sun.com/docs/books/performance/1st_edition/html/JPSwingModels.fm.html] .So, I think it's possible,Sir. Am I right? – Gomathi Jul 28 '12 at 06:12
  • It's ok, Sir. You have helped me so much! No one else would have helped me this much! I have too many things to learn. Thank you, Sir. I can manage with what I have now, Sir. Thank you once again, Sir. – Gomathi Jul 28 '12 at 06:29
  • We all have things to learn! Some one help me, I'm helping you & I hope you'll help some one as well ;) – MadProgrammer Jul 28 '12 at 06:37