![](/img/trans.png)
[英]What is the proper way to get the current look-and-feel's component background color in Swing?
[英]What is the proper way to set initially focused component for a dialog in Swing?
我有一个潜伏的错误,即在弹出包含文本字段的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
'文本字段确实获得了焦点,因此很明显有一种方法可以做到这一点。
我不知道规范的解决方案,但是您可以尝试只进行一次调用以在窗口侦听器中的事件线程上排队。 例如
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowActivated(WindowEvent event) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textField.requestFocusInWindow();
}
});
}
});
其他可能的“麻烦”包括使用短的单次运行Swing计时器。
您是否考虑过直接子类化/初始化JDialog而不是使用JOptionPane?
Java之所以没有“ setFocusInWindow”,是因为在某些平台上,无法直接“设置”焦点(尽可能多地请求焦点)。
在我看来,对“ setVisible()”的调用似乎在EDT上放置了一个事件,以使窗口可见,这又将焦点从文本字段移开了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.