Reputation: 1003
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
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:
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
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
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
Reputation: 15333
You should use next8.equalsIgnoreCase(target8)
in place of next8.equals(target8)
for your search to be case insensitive.
Upvotes: 1
Reputation: 1589
For the case sensitive part, you can use String.compareToIgnoreCase()
.
Upvotes: 1