In order to have custom button captions in an input dialog, I created the following code:
String key = null;
JTextField txtKey = new JTextField();
in
I found a solution ! Very primitive, but works.
Just jump to the field by java.awt.Robot using key "Tab".
I've created utils method calls "pressTab(..)"
For example:
GuiUtils.pressTab(1); <------------- // add this method before popup show
int result = JOptionPane.showConfirmDialog(this, inputs, "Text search window", JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION)
{
}
If you should press multiple times on "Tab" to get your Component you can use below method:
GUIUtils.pressTab(3);
Definition:
public static void pressTab(int amountOfClickes)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
Robot robot = new Robot();
int i = amountOfClickes;
while (i-- > 0)
{
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
}
}
catch (AWTException e)
{
System.out.println("Failed to use Robot, got exception: " + e.getMessage());
}
}
});
}
If your Component location is dynamic, you can run over the while loop without limitation, but add some focus listener on the component, to stop the loop once arrived to it.
Better way to do it: create the JOptionPane using the constructor, override selectInitialValue to set the focus, and then build the dialog using createDialog.
// Replace by the constructor you want
JOptionPane pane = new JOptionPane(panel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
@Override
public void selectInitialValue() {
textArea.requestFocusInWindow();
}
};
JDialog dialog = pane.createDialog(owner, title);
dialog.setVisible(true);
I had the same problem with the RequestFocusListener() not working on Linux, after following the discussion on http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5018574 I found that adding an invokeLater fixed it for now...
public class RequestFocusListener implements AncestorListener
{
public void ancestorAdded(final AncestorEvent e)
{
final AncestorListener al= this;
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
JComponent component = (JComponent)e.getComponent();
component.requestFocusInWindow();
component.removeAncestorListener( al );
}
});
}
public void ancestorMoved(AncestorEvent e) {}
public void ancestorRemoved(AncestorEvent e) {}
}
public static String getPassword(String title) {
JPanel panel = new JPanel();
final JPasswordField passwordField = new JPasswordField(10);
panel.add(new JLabel("Password"));
panel.add(passwordField);
JOptionPane pane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
@Override
public void selectInitialValue() {
passwordField.requestFocusInWindow();
}
};
pane.createDialog(null, title).setVisible(true);
return passwordField.getPassword().length == 0 ? null : new String(passwordField.getPassword());
}
Try this
String key = null;
JTextField txtKey = new JTextField();
Object[] foo = {pleaseEnterTheKey, txtKey};
int answerKey = JOptionPane.showOptionDialog(this, foo, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, foo[1]);
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
passing null as the last argument is the solution. At least it worked for me.
String key = null;
JTextField txtKey = new JTextField();
int answerKey = JOptionPane.showOptionDialog(this, new Object[] {pleaseEnterTheKey, txtKey}, decryptionKey, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] {okCaption, cancelCaption}, null);
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
But even this solution bring another problem:
Focused component and Default component are different. Default component or default button is the button which its onclick fires if you press ENTER KEY
.The last argument define the default component which gets the focus too and passing null brings the problem of having no default component!
I solved it for my code this way but I guess it is not a best practice:
String key = null;
final JTextField txtKey = new JTextField();
txtKey.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == 10) { //enter key
Container parent = txtKey.getParent();
while (!(parent instanceof JOptionPane)) {
parent = parent.getParent();
}
JOptionPane pane = (JOptionPane) parent;
final JPanel pnlBottom = (JPanel) pane.getComponent(pane.getComponentCount() - 1);
for (int i = 0; i < pnlBottom.getComponents().length; i++) {
Component component = pnlBottom.getComponents()[i];
if (component instanceof JButton) {
final JButton okButton = ((JButton)component);
if (okButton.getText().equalsIgnoreCase(okCaption)) {
ActionListener[] actionListeners = okButton.getActionListeners();
if (actionListeners.length > 0) {
actionListeners[0].actionPerformed(null);
}
}
}
}
}
}
});