【发布时间】:2015-01-25 15:05:05
【问题描述】:
在弹出包含文本字段的JOptionPane 后,我有一个潜伏的错误,焦点偶尔不会落在我想要的文本字段上。
我最终把它归结为一个合理的例子:
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Component;
public class FocusIssueTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// The real thing has many more components in there,
// but I removed them for the demo.
MyInputPane myInputPane = new MyInputPane();
myInputPane.showDialog(null);
}
});
}
public static class MyInputPane extends JPanel {
private final JTextField textField;
protected MyInputPane() {
textField = new JTextField();
textField.selectAll();
textField.setColumns(30);
setLayout(new BorderLayout());
add(textField, BorderLayout.CENTER);
}
public boolean showDialog(Component parentComponent) {
final JOptionPane optionPane = new JOptionPane(
this, JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION);
JDialog dialog = optionPane.createDialog(
parentComponent, "Select a Thing");
/* Attempted solution #1 - wait until the window is active
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowActivated(WindowEvent event) {
textField.requestFocusInWindow();
}
});
*/
/* Attempted solution #2 - camickr's RequestFocusListener
textField.addAncestorListener(new AncestorListener() {
@Override
public void ancestorAdded(AncestorEvent event) {
JComponent component = event.getComponent();
component.requestFocusInWindow();
component.removeAncestorListener(this);
}
@Override
public void ancestorRemoved(AncestorEvent event) {
}
@Override
public void ancestorMoved(AncestorEvent event) {
}
});
*/
/* Attempted solution #3 - HierarchyListener
textField.addHierarchyListener(new HierarchyListener() {
@Override
public void hierarchyChanged(HierarchyEvent event) {
Component component = event.getComponent();
if ((HierarchyEvent.SHOWING_CHANGED &
event.getChangeFlags()) != 0 &&
component.isShowing()) {
component.requestFocusInWindow();
component.removeHierarchyListener(this);
}
}
});
*/
// Attempted solution #4 - appears to work but can't be
// right, because eww.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
textField.requestFocusInWindow();
}
});
}
});
}
});
dialog.setVisible(true);
Object selectedValue = optionPane.getValue();
return selectedValue instanceof Integer &&
(int) selectedValue == 0;
}
}
}
尝试的解决方案 #1 到 #3 都未能将焦点放在文本字段中。尝试的解决方案 #4 可行,但必须使用三层嵌套的 SwingUtilities.invokeLater 调用不可能是正确的方法。
那么是正确的方法是什么?
我注意到 JOptionPane.showInputDialog' 文本字段确实获得焦点,所以显然有办法做到这一点。
【问题讨论】:
标签: java swing focus joptionpane