Gomathi
Gomathi

Reputation: 1003

JTextField needs to get blank and also make case insensitive search

I have two problems while searching for a text in a JTable:

1) For example, in JTextField I must initially have a 'Search Text' in transparent manner and if I click on it, the textfield must become blank and we can enter text there. How to achieve this in Java Swing?

2) My search coding is,

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;
}
}

But it is case-sensitive. I want it to be case-insensitive search. Where should I make changes in this? Also, for eg, if there is a text 'abc' and now I need to type the entire word 'abc'. Is there any way such that, if I type 'a' or 'bc' it would take me to that cell?

Kindly guide me. Thanks in advance.

Upvotes: 0

Views: 809

Answers (5)

kleopatra
kleopatra

Reputation: 51535

yeah - I'm aware that developers love to re-invent the wheel :-) Biased me prefers to use my favourite framework SwingX which already has all necessary building blocks:

  • automatic search support working the same way across all collection components
  • WYMIWYS (what-you-match-is-what-you-see), that is it uses the actual string representation in the renderering component instead of a dumb toString
  • search components are pluggable

That's the theory, at least, so on to eating my own dog food: the default findbar - that's the component to use for incremental search, that is searching the target while typing - uses a plain text field instead of the required prompt field. A custom implementation:

/**
 * A custom JXFindBar which uses a JXTextField instead of a plain as super.
 */ 
public static class PromptSearchBar extends JXFindBar {

    /**
     * Overridden to replace the plain text field in super
     * with a JXTextField (which supports prompts).
     */
    @Override
    protected void initComponents() {
        super.initComponents();
        searchField = new JXTextField() {
            @Override
            public Dimension getMaximumSize() {
                Dimension superMax = super.getMaximumSize();
                superMax.height = getPreferredSize().height;
                return superMax;
            }

        };
        searchField.setColumns(getSearchFieldWidth());
        ((JXTextField) searchField).setPrompt(getUIString(SEARCH_FIELD_LABEL));
    }

    /**
     * Overridden to update the prompt in addition to super
     */
    @Override
    protected void updateLocaleState(Locale locale) {
        super.updateLocaleState(locale);
        ((JXTextField) searchField).setPrompt(getUIString(SEARCH_FIELD_LABEL, locale));
    }
    /**
     * Overridden to not add the search label.
     */
    @Override
    protected void build() {
        setLayout(new FlowLayout(SwingConstants.LEADING));
        add(searchField);
        add(findNext);
        add(findPrevious);
    }

}

Installing in custom code:

SearchFactory factory = new SearchFactory() {

    @Override
    public JXFindBar createFindBar() {
        return new PromptSearchBar();
    }

};
SearchFactory.setInstance(factory);
factory.setUseFindBar(true);

That's it - focus a JXTable, JXTree, JXList, ... press ctr-f and type away in the searchfield: the next matching cell will be highlighted.

Upvotes: 1

MadProgrammer
MadProgrammer

Reputation: 347314

I use a custom paint method

@Override
protected void paintComponent(Graphics g) {

    super.paintComponent(g);

    String label = getLabel();
    if (label != null && (getText() == null || getText().length() == 0)) {

        Insets insets = getInsets();
        int width = getWidth() - (insets.left + insets.right);
        int height = getHeight() - (insets.top + insets.bottom);

        // This buffer should be created when the label is changed
        // or the size of the component is changed...
        BufferedImage buffer = ImageUtilities.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        Graphics2D g2d = buffer.createGraphics();

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(getForeground());
        g2d.setFont(getFont());

        FontMetrics fm = g2d.getFontMetrics();

        Composite comp = g2d.getComposite();
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f));

        int textHeight = fm.getHeight();

        int x = insets.left;
        int y = ((height - textHeight) / 2) + fm.getAscent();

        g2d.drawString(label, 0, y);

        g2d.dispose();

        g.drawImage(buffer, insets.left, insets.top, this);

    }

}

I've had some issues with it running on MacOS, hence the use of BufferedImage but it should work fine.

I typically wait until the user has typed in the field before clearing the label, but you could use a focus listener and flag to trigger the process instead

UPDATED with FOCUS LISTENER

public class MyTextField extents JTextField implements FocusListener {

    private boolean hasFocus = false;

    public void addNotify() {
        super.addNotify();
        addFocusListener(this);
    }

    public void removeNotify() {
        removeFocusListener(this);
        super.removeNotify();
    }

    public void focusGained(FocusEvent evt) {

        hasFocus = true;

    }

    public void focusLost(FocusEvent evt) {

        hasFocus = false;

    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        String label = getLabel();
        if (!hasFocus && label != null && (getText() == null || getText().length() == 0)) {
            // As above...
        }
    }
}

Or something to that effect

Upvotes: 2

Kumar Vivek Mitra
Kumar Vivek Mitra

Reputation: 33544

1. Create a hint for your JTextView. See this example http://code.google.com/p/xswingx/

2. Use equalsIgnoreCase( ) for comparison with case-Insensitivity...

////////////////////EDITED PART//////////////////////

3. If you dont want to implement a hint as i mentioned in point 1, then use FocusListener.

Eg:

JTextField textField = new JTextField("A TextField");
textField.addFocusListener(this);
public void focusGained(FocusEvent e) {

        textField = "" ;
}

See this for more details:

http://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html

Upvotes: 3

gprathour
gprathour

Reputation: 15333

You should use next8.equalsIgnoreCase(target8) in place of next8.equals(target8) for your search to be case insensitive.

Upvotes: 1

Autar
Autar

Reputation: 1589

For the case sensitive part, you can use String.compareToIgnoreCase().

Upvotes: 1

Related Questions