I am writing Bing/Google instant search kind of feature in combo box, so this combo box provides suggestions to the user based on what he has typed. The program works like a charm but their is one bug that I am unable to figure out how to solve. The problem is, the first character typed is recognised once the second the character has been typed, same goes for other position of characters too.
Here is the code:
public MyClass extends JFrame
{
private Document doc;
public MyCode()
{
comboxBox= new JComboBox();
Handler handle = new Handler();
JTextComponent comp = (JTextComponent) comboBox.getEditor().getEditorComponent();
doc = comp.getDocument().addDocumentListener(handle);
comboBox.addKeyListener(handle);
}
private class Handler implements DocumentListener,KeyListener
{
String dataTobeSearched= "";
#Override
public void changedUpdate(DocumentEvent event) {
try
{
dataTobeSearched = doc.getText(0, doc.getLength());
System.out.println("Data to be searched "+dataTobeSearched);
}
catch(Exception e)
{
e.printStackTrace();
}
}
#Override
public void keyPressed(KeyEvent event) {
changedUpdate(null);
}
}
What am I doing wrong?
I added the keyListener to the combobox editor because the DocumentListener wasn't getting invoked when something was being typed in the combobox? If there is an other easy alternative to this, then please share it.
How can I solve the above stated problem?
Wrap the call inside changedUpdate() in SwingUtilities.invokeLater()
According to the Java tutorial on Oracle website, changedUpdate() method will not work for plain text documents. If this is your case, use insertUpdate() and/or removeUpdate().
The recommendation of using SwingUtilities inside the method is still valid.
Related
I'm currently writing a small tool for sending sql queries to a database and recieving the according data.
Now to my problem:
I want to allow the user to enter a new search query or select from a "latest" list, where the last few queries are saved.
For that, I planned on using an editable JComboBox, but I'm having trouble diplaying multiple lines of text in the box itself.
The reason I want to do that, is because sql queries can get quite long and since I want make the box editable and at the same time keep the frame clean.
I've found ways to display multiple lines in the dropdown menu, but nothing for the box itself.
Thank you in advance and please forgive me if I overlooked something simple ;)
Greetings
Zeus
Extended editing functionality is supplied by the ComboBoxEditor, this allows you to define the actual component which is used as the combobox's editor
Based on your requirements, you're going to need (at the very least) a JTextArea, to provide (optionally) word wrapping and multiple lines
A rough and ready example might look something like this...
public class TextAreaComboBoxEditor implements ComboBoxEditor {
private JTextArea ta = new JTextArea(4, 20);
private JScrollPane sp = new JScrollPane(ta);
public TextAreaComboBoxEditor() {
ta.setWrapStyleWord(true);
ta.setLineWrap(true);
}
#Override
public Component getEditorComponent() {
return sp;
}
#Override
public void setItem(Object anObject) {
if (anObject instanceof String) {
ta.setText((String) anObject);
} else {
ta.setText(null);
}
}
#Override
public Object getItem() {
return ta.getText();
}
#Override
public void selectAll() {
ta.selectAll();
}
#Override
public void addActionListener(ActionListener l) {
}
#Override
public void removeActionListener(ActionListener l) {
}
}
This doesn't support ActionListener, as JTextArea uses the Enter key for it's own purposes. If you wanted to, you could use the key bindings API to add your own Action that can trigger the ActionListeners, for that, you'd need to supply a List or other means for managing them so you can call them back
I my app I have many of jTextFields. How can I validate all of JtextField?
I try something like this:
if((jTextField1.getText.length()<3) || (jTextField2.getText.length()<3) ||(jTextField1.getText.length()<3) ......){
........
}
What is a best way to validate text fields ?
Put all the fields in a List of some kind and loop over them
Use one or more InputVerify to perform post validation of the field, see Validating Input for more details
Use one or more DocumentFilters to do real-time validation, see Implementing a Document Filter and DocumentFilter Examples for more details
You can do that in a callback, like when 'losing focus' event is fired:
jTextField1.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent e) {
JTextField f = (JTextField)e.getSource();
if((f.getText.length()<3) || (f.getText.length()<3) ||(f.getText.length()<3) ......){
// ........
}
}
#Override
public void focusGained(FocusEvent e) {
}
});
I enter a name on my JTextfield , But my table don't filter any thing!
My code:
public class UserPage_Admin extends JFrame {
JTable table;
UserModel model;
public UserPage_Admin() {
model = new UserModel(...);
TableRowSorter sorter = new TableRowSorter<TableModel>(model);
table = new JTable(model);
table.setRowSorter(sorter);
add(new JScrollPane(table), BorderLayout.CENTER);
add(panelForm(), BorderLayout.PAGE_START);
RowFilter<UserModel, Object> rf = null;
try {
rf = RowFilter.regexFilter(filterTF.getText(), 0);
} catch (PatternSyntaxException pse) {
return;
}
sorter.setRowFilter(rf);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(850, 600);
setVisible(true);
}
you are calling RowFilter.regexFilter(filterTF.getText(), 0); in UserPage_Admin() constructor. How it supposed to read the text from the filterTF. I think you should call it from an Action Event Listener assigned to a JButton which will be called upon submitting(clicking) the text as follows:
submitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String text = filterText.getText();
if (text.length() == 0) {
sorter.setRowFilter(null);
} else {
sorter.setRowFilter(RowFilter.regexFilter(text, 0));
}
}
});
If you want to use Filtering upon user key type event, add key listener to the text field you are taking input filter-string.
filterTxtFeild.addKeyListener(new KeyAdapter() {
public void keykeyReleased(KeyEvent evt) {
// on each key type event filter.
// put your filter code as submit button
}
});
However, as it is suggested in the comments below, to work with Swing Text Component, one should have used the Document.addDocumentListener(DocumentListener). A Swing text component uses a Document to represent its content. Document events occur when the content of a document changes in any way. Add the document listener as follows:
filterTxtFeild.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
// put your filter code here upon data insertion
}
#Override
public void removeUpdate(DocumentEvent e)
{
//put your filter code here upon data removal
}
#Override
public void changedUpdate(DocumentEvent e) {}
});
Edit: Why DocumentListener is preferable ?
If we want validation of input in the data source, using KeyEvent while filtering the data you’ll find it does not reflect the user’s keystroke and input events are sent to the listeners before they are processed by the data source. suppose that when we want an user name to be entered, someone input a text like "$%^&". On such invalid input, KeyEvent will still be fired even though no valid changes has been made to data source. But, DocumentListeners are notified only when a valid changes has been made to the data source. Data entry components produce events in which a validator can listen for asynchronously, one should never modify the contents of a text component from within a DocumentListener. If we do so, the program will likely deadlock.
I enter a name on my JTextfield , But my table don't filter any thing!
there are two ways, you don't mentioned expected logics
filtering on KeyTyped from DocumentListener (your code talking about ???)
from ActionListener invoked from ENTER Key
both a.m. ways added to JTextField
then there are another two very important options
filtering in whole JTables, columns and rows (your code talking about ???)
in one (quite possible in two or more, never tried) columns
everything depends of your goal
everything by using standard methods implemented in API
You simply fail to use sorter after initializing it. You should call JTable.setRowSorter().
In My Eclipse Project, I have a
Text custom_text = new Text(....);
Now I add a listener -
custom_text.addKeyListener(new
KeyListener(){
#Override public void keyPressed(KeyEvent event) {
}
#Override public void
keyReleased(KeyEvent event) {
System.err.println("event
"+event.getSource()));
} });
Anyhow, I am not getting the source name,despite I am getting the output as Text {}.
Well I want to get the source name ie custom_text .
How to get the output in a listener as
custom_text
IMHO you can not the name of the variable, holding the reference to your textfield. It is also not really of any use to know the name of the variable, since you can have many referencing variables.
With .getSource() you get a full reference to the widget itself, so you can deal with it in any way.
You can use event.widget to identify wich widget notify event.
But general approach is relaying with anonymous listener.
because it can use more readable method name which is more fit to subject of controller.
Text nameField, emailField = ...
nameField.addListener(SWT.KeyUp, new Listener(){
public void handleEvent(Event e){
handleNameEdited();
}
});
emailField.addListener(SWT.KeyUp, new Listener(){
public void handleEvent(Event e){
handleEmailEdited();
}
});
I have this code:
this.trigger = new Trigger();
this.presentationModel = new PresentationModel(this.personBean, this.trigger);
final ValueModel firstNameAdapter = presentationModel.getBufferedModel("firstName");
final JTextField firstNameTextField = BasicComponentFactory.createTextField(firstNameAdapter);
and
firstNameTextField.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
trigger.triggerCommit();
}
});
So when I push the enter button on the JTextField, I expect the value in my ValueModel class to be the same as the value in my JTextField. This doesn't happen unless I click outside the JTextField, then back inside the JTextField, and then push enter. If I just type in the text and hit enter, the ValueModel does not get the updated value. I am stuck on this problem, can anybody help?
BTW, I used this link for figuring out JGoodies in the first place: JGoodies Tutorial
I hope I am understanding your question correctly.
You need to get the text in the text field and set it in the ValueModel.
firstNameTextField.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
//this get the text from the text field
String firstName = firstNameTextField.getText();
//now write your code to set the firstname into the ValueModel
trigger.triggerCommit();
}
});
I looked through the JGoodies API (should have done this sooner) and found an unexpected static call, Bindings.commitImmediately()
If I call this method before my call to trigger.triggerCommit(), everything works as expected :)
Create a text field that commits on each key typed instead of when focus is lost:
BasicComponentFactory.createTextField(firstNameAdapter, false);
Also, you should consider architecting your program to not use buffered models. I find that they make things more complicated and tricky, and think I saw Karsten Lentzsch recommending not to use them as well in a mailing list.
The most useful way for me to learn JGoodies was to look at the tutorial code for the JGoodies binding and validation libraries.