I have a JComboBox, once every second I want to retreive a set of strings from a database and set those strings to the contents of the JComboBox, and one of them as the currently selected value. But I also want the user to be able to edit the JComboBox and add a value to the database and set it as the current value.
I want to the be able to detect when characters are entered into the JComboBox, so I can reset a count down which prevents updating the JComboBox as long as it's not zero. My first instinct was to use a KeyListener but the Java tutorial on combo boxes says this,
Although JComboBox inherits methods to register listeners for
low-level events — focus, key, and mouse events, for example — we
recommend that you don't listen for low-level events on a combo box.
And they go on to say that the events fired may change depending on the look and feel.
This is a little dicey, but it should work to listen to the Document updates on the Editor component (A JTextField).
JComboBox cb = new JComboBox();
Component editor = cb.getEditor().getEditorComponent();
if (editor instanceof JTextField) {
((JTextField) editor).getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent documentEvent) {
//To change body of implemented methods use File | Settings | File Templates.
}
#Override
public void removeUpdate(DocumentEvent documentEvent) {
//To change body of implemented methods use File | Settings | File Templates.
}
#Override
public void changedUpdate(DocumentEvent documentEvent) {
//To change body of implemented methods use File | Settings | File Templates.
}
});
}
Those *Update(DocumentEvent documentEvent) methods should get called for every character typed/deleted from the JComboBox.
I would like to add that the changedUpdate method will not fire a notification for plain text documents. If you are using a plain text text component, you must use insertUpdate and/or removeUpdate.
I recently had to use a document listener as a way of disabling/enabling a button if the user was editing the combo box. I did something like this and worked very well:
public class MyDocumentListener implements DocumentListener
{
#Override
public void insertUpdate(DocumentEvent e)
{
setChanged();
notifyObservers(true);
}
#Override
public void removeUpdate(DocumentEvent e)
{
setChanged();
notifyObservers(false);
}
#Override
public void changedUpdate(DocumentEvent e)
{
// Not used when document is plain text
}
}
Then, I added this listener to the combo box like this:
((JTextComponent) combobox.getEditor().getEditorComponent())
.getDocument().addDocumentListener(new MyDocumentListener());
This works because the document associated with the combo box is plain text. When I used changedUpdate it did not.
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 am trying to add multiple text fields in to a single focus listener to be executed, currently i have added a text field but i cant figure out how to add multiple text fields to it,
i think its way better than creating a focus listener for each textfield.
Usually tha anser is: "it depends..."
but in your case Id say: each textfield should have its own listener (instance).
The reason is that you change the textfields content.
When you do this in only one Listener instance then you either change all the textfields any time the event occurs regarless of which textfield was affected, or you end up with a if/else cascade needing a new entry if you add another textfield.
I suggest that you create a named inner class for the Listener giving it a Textfield as parameter:
class MyTextFiledFocusListener implements FocusListener {
private final JTextFiled textField;
MyTextFiledFocusListener(JTextFiled textField){
this.textField = textField;
textField.addFocusListener(this);
}
public void focusGained(FocusEvent e)
{
textField.setText("");
}
public void focusLost(FocusEvent e)
{
// nothing
}
}
and the bit you posted changes to:
new MyTextFiledFocusListener(JT_id);
Just for the records:
quite a lot Swing related interfaces with more than one method have default implementations with empty methods (the pre java8 solution for default methods) so does FocusListener. These default implementation are usually called *Adapter. Therefore you could shorten your code when you extend FocusAdapter insted of implementing FocusListener:
class MyTextFiledFocusListener extends FocusAdapter {
private final JTextFiled textField;
MyTextFiledFocusListener(JTextFiled textField){
this.textField = textField;
textField.addFocusListener(this);
}
public void focusGained(FocusEvent e)
{
textField.setText("");
}
}
What about something like this?
FocusListener clearFields = new FocusListener() {
public void focusGained(FocusEvent e)
{
JT_id.setText("");
JT_name.setText("");
JT_add.setText("");
JT_cno.setText("");
JT_email.setText("");
}
public void focusLost(FocusEvent e)
{
// nothing
}
});
JT_id.addFocusListener(clearFields);
JT_name.addFocusListener(clearFields);
JT_add.addFocusListener(clearFields);
JT_cno.addFocusListener(clearFields);
JT_email.addFocusListener(clearFields)
You will still need to add a focus listener to all of the text-fields to avoid the situation where clicking/focusing on the first one (JT_id) will clear all of them while clicking/focusing on the others would do nothing.
Or, you know, the alternative - assign each textfield a focuslistener that only clears that field.
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();
}
});