This question already has answers here:
Validation of text fields and contact no text field
(2 answers)
Closed 6 years ago.
So I just started reading about DocumentListeners and some other Action Listeners today but I can't get my JButton to revert to setEnabled(false) state when any of the text fields are empty. Is this something to do with the caret position or is there a proper way of reverting it to original state setEnabled(false) when any of the text fields are empty.
Here's what I've written so far.
public class home extends javax.swing.JPanel {
public home() {
JPasswordField currentPasswordJPasswordField;
JPasswordField newPasswordJPasswordField;
JPasswordField reTypeNewPasswordJPasswordField;
currentPasswordJPasswordField.getDocument().addDocumentListener(new textFieldListener(saveNewPasswordButton));
newPasswordJPasswordField.getDocument().addDocumentListener(new textFieldListener(saveNewPasswordButton));
reTypeNewPasswordJPasswordField.getDocument().addDocumentListener(new textFieldListener(saveNewPasswordButton));
}
public static class textFieldListener implements DocumentListener {
JButton btn;
public textFieldListener(JButton button) {
btn = button;
}
#Override
public void insertUpdate(DocumentEvent e) {
btn.setEnabled(true);
}
#Override
public void removeUpdate(DocumentEvent e) {
btn.setEnabled(true);
}
#Override
public void changedUpdate(DocumentEvent e) {
btn.setEnabled(true);
}
}
}
When I type something on the textfield it enables the save button as expected. But when I press backspace to clear all the text, save button won't revert to setEnabled(false).
I'd appreciate any response. I just started to learn this. I also want to know if I can put the action listeners in a separate .java file. If so, how can I apply the listeners to my main class.
Thanks.
Your basic approach is correct, using a DocumentListener, but you don't seem to be checking the length of the Document's contents at any point
This is a really simple example, but until all three fields have something in them, the button won't be enabled.
You could extend the idea by also checking to see if the first two fields match, but I'll leave that up to you
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JPasswordField currentPasswordJPasswordField;
private JPasswordField newPasswordJPasswordField;
private JPasswordField reTypeNewPasswordJPasswordField;
private List<JTextComponent> requiredFields = new ArrayList<>(25);
private JButton okay;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(2, 2, 2, 2);
gbc.gridwidth = GridBagConstraints.REMAINDER;
currentPasswordJPasswordField = makePasswordField();
newPasswordJPasswordField = makePasswordField();
reTypeNewPasswordJPasswordField = makePasswordField();
add(currentPasswordJPasswordField, gbc);
add(newPasswordJPasswordField, gbc);
add(reTypeNewPasswordJPasswordField, gbc);
okay = new JButton("Ok");
add(okay);
updateState();
}
protected JPasswordField makePasswordField() {
JPasswordField field = new JPasswordField(20);
field.getDocument().addDocumentListener(new DocumentHandler());
requiredFields.add(field);
return field;
}
protected void updateState() {
boolean enabled = true;
for (JTextComponent field : requiredFields) {
if (field.getDocument().getLength() == 0) {
enabled = false;
break;
}
}
okay.setEnabled(enabled);
}
public class DocumentHandler implements DocumentListener {
#Override
public void insertUpdate(DocumentEvent e) {
updateState();
}
#Override
public void removeUpdate(DocumentEvent e) {
updateState();
}
#Override
public void changedUpdate(DocumentEvent e) {
updateState();
}
}
}
}
You can add a KeyListener to each of the text fields and update the button from inside the anonymous inner class.
currentPasswordJPasswordField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(currentPasswordJPasswordField.getText().length() > 0 &&
newPasswordJPasswordField.getText().length() > 0 &&
reTypeNewPasswordJPasswordField.getText().length() > 0) {
btn.setEnabeld(true);
} else {
btn.setEnabled(false);
}
}
});
newPasswordJPasswordField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(currentPasswordJPasswordField.getText().length() > 0 &&
newPasswordJPasswordField.getText().length() > 0 &&
reTypeNewPasswordJPasswordField.getText().length() > 0) {
btn.setEnabeld(true);
} else {
btn.setEnabled(false);
}
}
});
reTypeNewPasswordJPasswordField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if(currentPasswordJPasswordField.getText().length() > 0 &&
newPasswordJPasswordField.getText().length() > 0 &&
reTypeNewPasswordJPasswordField.getText().length() > 0) {
btn.setEnabeld(true);
} else {
btn.setEnabled(false);
}
}
});
Related
I created custom buttons for maximize, minimize and exit. And everything is working, with one exception, program does not remember in which state window was, before minimization. So my question is, is there a way, program to remember window state before minimization, and restore that state, and not to return only on NORMAL state?
My solution for:
maximize:
JButton btnO = new JButton("O");
btnO.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (frame.getExtendedState() == JFrame.MAXIMIZED_BOTH) {
frame.setExtendedState(JFrame.NORMAL);
} else {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
});
and Minimize:
JButton btnMinimize = new JButton("-");
btnMinimize.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.setExtendedState(JFrame.ICONIFIED);
}
});
You can take the ComponentListener approach and restore its state when the component (in your case, the frame), is resized. Some extra comments inside the code.
Take a look at this example:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class FrameState extends JFrame {
private static final long serialVersionUID = 1965751967944243251L;
private int state = -1; // Variable to keep the last state.
public FrameState() {
super("Nothing :)");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton b = new JButton("-");
b.addActionListener(e -> {
state = getExtendedState(); //Store the state before "-" is pressed
setExtendedState(JFrame.ICONIFIED);
});
JButton o = new JButton("O");
o.addActionListener(e -> {
if (getExtendedState() == JFrame.MAXIMIZED_BOTH) {
setExtendedState(JFrame.NORMAL);
} else {
setExtendedState(JFrame.MAXIMIZED_BOTH);
}
});
getContentPane().setLayout(new FlowLayout());
getContentPane().add(o);
getContentPane().add(b);
setSize(new Dimension(300, 300));
setLocationRelativeTo(null);
addComponentListener(new ComponentListener() {
#Override
public void componentShown(ComponentEvent arg0) {
}
#Override
public void componentResized(ComponentEvent arg0) {
if (state != -1) {
setExtendedState(state); //Restore the state.
state = -1; //If it is not back to -1, window won't be resized properly by OS.
}
}
#Override
public void componentMoved(ComponentEvent arg0) {
}
#Override
public void componentHidden(ComponentEvent arg0) {
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
FrameState f = new FrameState();
f.setVisible(true);
});
}
}
You can use this code in JButton to maximize and restore JFrame.
In order to perform this function, you have import JFrame even though the JFrame has been extended in your java class.
if(getExtendedState()==NORMAL)
{
setExtendedState(MAXIMIZED_BOTH);
}
else
{
setExtendedState(NORMAL);
}
I'm trying to check a JFormattedTextField after a value has been entered to make sure it does not match any other values entered in the other similar fields. It becomes a real pain if this check happens repeatedly while the user is typing because I want to provide an error message and I need to implement a number of changes if the value changes. But inputs like 123 will match 12 before the 3 is typed even though no error has really been made yet. Thus the need for a delay. So I'm trying to use a document listener but delay it until the user has validated (as accepted by the text field, by action or shifting focus) the entry.
I thought I had a good method, and it nearly works. My plan was to use a document listener to set up focus and action listeners. Unfortunately, I seem to end up with tons of focus and action listeners since the document listener keeps adding them. That means the error message and subsequent processing happen a ridiculous number of times instead of once. I've tried two work-arounds: 1) remove focus and action listeners before adding new ones, and 2) use a boolean to mark the existence of the focus and action listeners to avoid creating them again.
sscce (I'm new here, should I leave out all the includes?):
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JTextField textField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textField = new JTextField("Change this.");
textField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
trigger();
}
public void removeUpdate(DocumentEvent e) {
trigger();
}
public void changedUpdate(DocumentEvent e) {
trigger();
}
public void trigger() {
textField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField.getText());
}
});
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField.getText());
}
});
}
});
frame.add(textField);
}
}
So attempted fix 1 was to place textField.removeFocusListener(null) and textField.removeActionListener(null) just before the two textField.add... lines. Nothing changed from attempted fix 1. Attempted fix 2 was to create a boolean triggeringEvent outside of trigger() and then start trigger() with if(triggeringEvent == false) { triggeringEvent = true; ... all the focus and action listener lines. Attempted fix 2 just left me with nothing triggering at all.
Thank you for any insight anyone can provide!!!
Edit: I had tried Boann's addChangeListener, but that triggers incessantly, too, and it even triggers when the value hasn't been changed.
Edit: I thought I found a solution by adjusting attempted fix 2, but it fails with more than one JTextField:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JTextField textField;
private boolean eventTrigger = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textField = new JTextField("Change this.");
textField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField.getText());
eventTrigger = false;
}
});
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField.getText());
eventTrigger = false;
}
});
}
});
frame.add(textField);
}
}
You can see in this. If you start hopping between fields there are a whole bunch of extra times it triggers. It works fine for the first one you try adjusting, but then it fails.
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Tester {
private JFrame frame;
private JPanel panel;
private JTextField textField1;
private JTextField textField2;
private boolean eventTrigger = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Tester window = new Tester();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Tester() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(50, 50, 200, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new GridLayout(0,1,0,0));
textField1 = new JTextField("Change the first.");
textField2 = new JTextField("Change the second.");
textField1.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField1.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField1.getText());
eventTrigger = false;
}
});
textField1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField1.getText());
eventTrigger = false;
}
});
}
});
textField2.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void removeUpdate(DocumentEvent e) {
if(eventTrigger == false) {
trigger();
}
}
public void changedUpdate(DocumentEvent e) {
}
public void trigger() {
eventTrigger = true;
textField2.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
System.out.println("You changed the text to: " + textField2.getText());
eventTrigger = false;
}
});
textField2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("You changed the text to: " + textField2.getText());
eventTrigger = false;
}
});
}
});
panel.add(textField1);
panel.add(textField2);
frame.add(panel);
}
}
I have a very small question. Now I wrote the code for creating a virtual keyboard. I want the color of the button to change when it is typed. Here is my code:
public class ButtonColor implements KeyListener {
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar()=='a') {
A.setBackground(Color.red);
}
}
}
]
Whenever I press A, nothing happens. When I add this line:
JOptionPane.showMessageDialog(null, "A was typed");
then type a, the message appears and after I click OK the button changes color. Why does that happen? How can I fix this problem?
There could be any number of reasons why this doesn't work for you, for starters, the button may be transparent (opaque == false)
I would strongly recommend against KeyListener in favour of Key Bindings as KeyListener has issues with focus...
For example...
The following uses the key bindings API in order to respond to a given key stroke, depending on if it's a key press or release event, it will set the background color and opacity state accordingly and even sets the buttons pressed state...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class KeyboardTest {
public static void main(String[] args) {
new KeyboardTest();
}
public KeyboardTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JButton btnA = createButton("A");
JButton btnB = createButton("B");
JButton btnC = createButton("C");
JButton btnD = createButton("D");
JButton btnE = createButton("E");
add(btnA);
add(btnB);
add(btnC);
add(btnD);
add(btnE);
addKeyBinding(btnA, "A", KeyEvent.VK_A);
addKeyBinding(btnB, "B", KeyEvent.VK_B);
addKeyBinding(btnC, "C", KeyEvent.VK_C);
addKeyBinding(btnD, "D", KeyEvent.VK_D);
addKeyBinding(btnE, "E", KeyEvent.VK_E);
}
protected JButton createButton(String text) {
JButton btn = new JButton(text);
btn.setFocusable(false);
return btn;
}
protected void addKeyBinding(JButton btn, String name, int virtualKey) {
ActionMap am = getActionMap();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(virtualKey, 0, false), name + ".pressed");
im.put(KeyStroke.getKeyStroke(virtualKey, 0, true), name + ".released");
am.put(name + ".pressed", new KeyAction(btn, true));
am.put(name + ".released", new KeyAction(btn, false));
}
}
public class KeyAction extends AbstractAction {
private JButton btn;
private boolean highlight;
public KeyAction(JButton btn, boolean highlight) {
this.btn = btn;
this.highlight = highlight;
}
#Override
public void actionPerformed(ActionEvent e) {
if (highlight) {
btn.getModel().setPressed(true);
btn.setBackground(Color.RED);
btn.setOpaque(true);
} else {
btn.getModel().setPressed(false);
btn.setBackground(null);
btn.setOpaque(false);
}
}
}
}
Updated
If you also use btn.getModel().setArmed(...); you will get a much more "bolded" response, which produces better visual feedback...IMHO
i got stuck at adding a button to a JComboBox editor, I succeeded to add a button but I got some issues like when I first enter to the editor an action perform event gets fired which is unacceptable and the other is I can't get the text typed.
Result:
Problems:
#Override
public Component getEditorComponent() {
return panel;
}
This is the problem, if I return panel.jtexfield I only get a text field without a button, so what's the trick here?
Here is my code
import Store.util.DatabaseHelper;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import org.hibernate.HibernateException;
import org.netbeans.lib.awtextra.AbsoluteLayout;
public class NewComboTest extends JFrame {
private ArrayList<Object> shopCart = new ArrayList<Object>();
private JComboBox cb;
private static final Object[] comboContents = {
"First", "Second", "Third", "Fourth", "Fifth"
};
public NewComboTest() {
super("New Combo Test");
setLayout(null);
cb = new JComboBox();
cb.setRenderer(new NewComboRenderer());
cb.setEditor(new NewComboEditor());
cb.setEditable(true);
cb.setSize(new Dimension(350, 100));
for (int i = 0; i < comboContents.length; i++) {
cb.addItem(comboContents[ i]);
}
cb.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("_____________" + cb.getSelectedItem());
shopCart.add(cb.getSelectedItem());
System.out.println("items added" + shopCart);
}
});
cb.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
System.out.println("KeyReleased" + cb.getEditor().getItem().toString());
populateModel(cb.getEditor().getItem().toString());
}
});
getContentPane().add(cb, new org.netbeans.lib.awtextra.AbsoluteConstraints(320, 200, 480, 50));
setSize(1200, 450);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] arg) {
new NewComboTest();
}
private class NewComboEditor extends JPanel implements ComboBoxEditor {
JTextField tf;
JButton eraseButton;
textPanel panel = new textPanel();
public NewComboEditor() {
}
#Override
public void addActionListener(ActionListener l) {
tf.addActionListener(l);
}
#Override
public Component getEditorComponent() {
return panel;
}
public Component getEditorComponent2() {
return panel;
}
#Override
public Object getItem() {
return tf.getText();
}
#Override
public void removeActionListener(ActionListener l) {
tf.removeActionListener(l);
}
#Override
public void selectAll() {
tf.selectAll();
}
#Override
public void setItem(Object o) {
if (o != null) {
tf.setText(tf.getText());
} else {
tf.setText("");
}
}
private class textPanel extends JPanel {
JTextField jTextField1 = new JTextField();
JButton jButton1 = new JButton();
public textPanel() {
setLayout(new BorderLayout());
jButton1.setBackground(new java.awt.Color(255, 255, 255));
jButton1.setForeground(new java.awt.Color(0, 51, 51));
jButton1.setText("X");
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jTextField1.setText("");
}
});
add(jTextField1, BorderLayout.CENTER);
add(jButton1, BorderLayout.EAST);
}
public String getText(){
return jTextField1.getText();
}
}
}
private class NewComboRenderer extends JLabel implements ListCellRenderer {
public NewComboRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
setBackground(isSelected ? Color.BLUE : Color.white);
setForeground(isSelected ? Color.white : Color.red);
return this;
}
}
/* public void populateModel(String text) throws HibernateException {
java.util.List l = DatabaseHelper.GetProductsBy(text);
for (Object object : l) {
cb.addItem(object);
}
ignore this its unnecessary.
*/
}
}
I also wish to set the text font and size to the same as the set up at the combo box.
The first set of problems I can see is, you define a JTextField and JButton in the NewComboEditor, but also define a textPanel, which contains all these things any way. But instead of using the components on the textPane, you use the newly created components (in the NewComboEditor) instead...In fact, I'm not even sure how that could work, because you never initilise these components (in the NewComboEditor), so there should be a NullPointerException...
If that wasn't enough problems, the JTextField and JButton aren't added to anything anyway...
Instead...
NewComboEditor shouldn't need to extend from anything (or it could extend from textPane instead if you really wanted to).
All references to the field should be made to the text field in the textPane
As an example...
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CustomComboBoxEditor {
public static void main(String[] args) {
new CustomComboBoxEditor();
}
public CustomComboBoxEditor() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JComboBox cb = new JComboBox();
cb.addItem("Apple");
cb.addItem("Banana");
cb.addItem("Orange");
cb.setEditable(true);
cb.setEditor(new MyComboBoxEditor());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(cb);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyComboBoxEditor implements ComboBoxEditor {
private EditorPane editorPane;
public MyComboBoxEditor() {
editorPane = new EditorPane();
}
#Override
public Component getEditorComponent() {
return editorPane;
}
#Override
public void setItem(Object anObject) {
editorPane.setText(anObject == null ? null : anObject.toString());
}
#Override
public Object getItem() {
return editorPane.getText();
}
#Override
public void selectAll() {
editorPane.selectAll();
}
#Override
public void addActionListener(ActionListener l) {
editorPane.addActionListener(l);
}
#Override
public void removeActionListener(ActionListener l) {
editorPane.removeActionListener(l);
}
}
public class EditorPane extends JPanel {
private JTextField field;
private JButton button;
public EditorPane() {
field = new JTextField(10);
button = new JButton("X");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
add(field, gbc);
gbc.weightx = 0;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx++;
add(button, gbc);
}
#Override
public void addNotify() {
super.addNotify();
field.requestFocusInWindow();
}
public void selectAll() {
field.selectAll();
}
public void setText(String text) {
field.setText(text);
}
public String getText() {
return field.getText();
}
public void addActionListener(ActionListener listener) {
field.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
field.removeActionListener(listener);
}
}
}
Now, if you want to set the field's properties to be the same as the combo box, I would simply pass a reference of the combo box to the editor and allow it to extract the properties you need (i.e. font, color, etc.)
So I have to create a jTextbox and a keyboard for an assignment. While I type, I need the corresponding jButton to change colour.
So currently, when I run, the focus is on the jTextbox, and I can type, but I can't set the focus to the button.
Some help would be greatly appreciated. Thank you
private void aButtonKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_A)
{
aButton.setBackground(Color.red);
}
}
private void aButtonKeyReleased(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_A)
{
aButton.setBackground(Color.LIGHT_GRAY);
}
}
private void sButtonKeyPressed(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_S)
{
sButton.setBackground(Color.red);
}
}
private void sButtonKeyReleased(java.awt.event.KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_S)
{
sButton.setBackground(Color.LIGHT_GRAY);
}
}
Have a common class which implements KeyListener and give that class to JButtons.
Have a Map to store Key Code and JButton
Map<Integer, JButton> keyCodeButtonMap = new HashMap<Integer, JButton>();
keyCodeButtonMap.put(KeyEvent.VK_A, aButton); // Example
Add all the KeyEvent Virtual Keys to the Map along with the correct button.
private void buttonKeyPressed(java.awt.event.KeyEvent evt) {
keyCodeButtonMap.get(evt.getKeyCode()).setBackground(Color.RED);
keyCodeButtonMap.get(evt.getKeyCode()).setForeground(Color.RED);
}
private void buttonKeyReleased(java.awt.event.KeyEvent evt) {
keyCodeButtonMap.get(evt.getKeyCode()).setBackground(Color.LIGHT_GRAY);
keyCodeButtonMap.get(evt.getKeyCode()).setForeground(Color.LIGHT_GRAY);
}
This should Ideally work.
I dont think you want to set focus to the JButton (or else you wont be able to type in JTextArea/JTextField etc), perhaps you want it to change its color and make it click when a certain character(s) are entered?
When using Swing components rather use KeyBindings as suggested by others.
Here is an example I made:
when . is pressed the button background will be changed to blue (and buttons method will called which to auto-inserts SPACE after '.'):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Test {
final JFrame frame = new JFrame();
final JTextField jtf = new JTextField(15);
final JButton button = new JButton("SPACE");
public Test() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void initComponents() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
insertSpace();
}
});
final Color defaultColor = button.getBackground();
jtf.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, 0, true), "period rel");
jtf.getActionMap().put("period rel", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
//button.doClick(); //I dont like this as it makes JBUtton look like its being clicked where as we want a color change
insertSpace();
button.setBackground(defaultColor);
}
});
jtf.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, 0), "period pressed");
jtf.getActionMap().put("period pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
button.setBackground(Color.CYAN);
}
});
frame.add(jtf, BorderLayout.NORTH);
frame.add(button, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private void insertSpace() {
String s = jtf.getText();
jtf.setText(s + " ");
}
}
You might want to see KeyBindings.
But if you really want KeyListener, try this.
yourJtextField.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e){
if( e.getKeyCode() == KeyEvent.VK_A ){
aButton.setBackground(yourColor);
}
}
#Override
public void keyReleased(KeyEvent e){
aButton.setBackground(yourDefaultColor);
}
});