java 在 JOptionPane.showOptionDialog() 中设置组件焦点
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6251665/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting component focus in JOptionPane.showOptionDialog()
提问by ehsun7b
In order to have custom button captions in an input dialog, I created the following code:
为了在输入对话框中有自定义按钮标题,我创建了以下代码:
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}, okCaption);
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
How can I move the focus(cursor) to the text field as the dialog is displayed?
如何在显示对话框时将焦点(光标)移动到文本字段?
UPDATE
更新
This does not work for me, I mean the textfield has no focus: OS: Fedora - Gnome
这对我不起作用,我的意思是文本字段没有焦点:操作系统:Fedora - Gnome
public class Test {
public static void main(String[] args) {
String key = null;
JTextField txtKey = new JTextField();
txtKey.addAncestorListener(new RequestFocusListener());
int answerKey = JOptionPane.showOptionDialog(null, new Object[]{"Please enter the key:", txtKey}, "Title", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[]{"OKKK", "CANCELLLL"}, "OKKK");
if (answerKey == JOptionPane.OK_OPTION && txtKey.getText() != null) {
key = txtKey.getText();
}
}
}
回答by camickr
Dialog Focusshows how you can easily set the focus on any component in a modal dialog.
Dialog Focus展示了如何轻松地将焦点设置在模态对话框中的任何组件上。
回答by Frank M.
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());
}
回答by ehsun7b
passing null as the last argument is the solution. At least it worked for me.
将 null 作为最后一个参数传递是解决方案。至少它对我有用。
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:
但即使是这个解决方案也会带来另一个问题:
Focusedcomponent and Defaultcomponent 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:
焦点组件和默认组件是不同的。默认组件或默认按钮是当您按下 时其 onclick 触发的按钮ENTER KEY
。最后一个参数定义了也获得焦点的默认组件,传递 null 会带来没有默认组件的问题!我以这种方式为我的代码解决了这个问题,但我想这不是最佳实践:
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);
}
}
}
}
}
}
});
回答by Jim Morris
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=5018574I found that adding an invokeLater fixed it for now...
我遇到了同样的问题,RequestFocusListener() 在 Linux 上不起作用,在遵循http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5018574上的讨论后,我发现添加 invokeLater 暂时修复了它。 ..
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) {}
}
回答by Udo Schuermann
The trick is to (a) use an AncestorListener on the text component to request focus, and when the focus is lost again (given to the default button), ask for focus a second time using a FocusListener on the text component (but don't keep asking for focus after that):
诀窍是 (a) 在文本组件上使用 AncestorListener 来请求焦点,当焦点再次丢失时(给默认按钮),在文本组件上使用 FocusListener 再次请求焦点(但不要之后继续要求焦点):
final JPasswordField accessPassword = new JPasswordField();
accessPassword.addAncestorListener( new AncestorListener()
{
@Override
public void ancestorRemoved( final AncestorEvent event )
{
}
@Override
public void ancestorMoved( final AncestorEvent event )
{
}
@Override
public void ancestorAdded( final AncestorEvent event )
{
// Ask for focus (we'll lose it again)
accessPassword.requestFocusInWindow();
}
} );
accessPassword.addFocusListener( new FocusListener()
{
@Override
public void focusGained( final FocusEvent e )
{
}
@Override
public void focusLost( final FocusEvent e )
{
if( isFirstTime )
{
// When we lose focus, ask for it back but only once
accessPassword.requestFocusInWindow();
isFirstTime = false;
}
}
private boolean isFirstTime = true;
} );
回答by ceklock
Better way to do it: create the JOptionPane using the constructor, override selectInitialValue to set the focus, and then build the dialog using createDialog.
更好的方法是:使用构造函数创建 JOptionPane,覆盖 selectInitialValue 以设置焦点,然后使用 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);
回答by mre
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();
}
回答by Adir D
I found a solution !Very primitive, but works.
我找到了解决方案!非常原始,但有效。
Just jump to the field by java.awt.Robotusing key "Tab". For example:
只需通过 java.awt 跳转到该字段。使用“Tab”键的机器人。例如:
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
If you should press multiple times on "Tab" to get your Component you can use below method:
如果您应该多次按“Tab”来获取您的组件,您可以使用以下方法:
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.
如果您的组件位置是动态的,您可以不受限制地运行 while 循环,但在组件上添加一些焦点侦听器,一旦到达它就停止循环。