我对Swing开发很新,希望我的问题不是一个愚蠢的问题.
我有一个以下问题.我正在跟踪焦点KeyboardFocusManager,听取属性permanentFocusOwner变化.但是,当焦点从一个控件变为另一个控件时,我会将permanentFocusOwner属性的中间更改为null.
当焦点位于其中一个面板或其子面板内时,我当前的UI逻辑正在对控件进行一些更改.然而,获得中间null打破这个逻辑.
我在谷歌搜索有关此问题的信息,没有发现任何相关信息.
问题是,这种行为是否是设计的,以及是否有某种方法可以解决中间空值.
这是再现上述行为的最小应用程序:
import java.awt.*;
import java.beans.*;
import javax.swing.*;
public class FocusNullTest extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
FocusNullTest self = new FocusNullTest();
self.setVisible(true);
}
});
}
public FocusNullTest() {
setSize(150, 100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = getContentPane();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
contentPane.add(new JButton("1"));
contentPane.add(new JButton("2"));
KeyboardFocusManager focusManager =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(
"permanentFocusOwner",
new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent e) {
System.out.println("permanentFocusOwner changed from: "
+ e.getOldValue());
System.out.println("permanentFocusOwner changed to : "
+ e.getNewValue());
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
日志输出是:
(程序启动,焦点自动设置为按钮1)
permanentFocusOwner从:null
permanentFocusOwner更改为:javax.swing.JButton [,0,18,41x26,(跳过)]
(单击按钮2)
permanentFocusOwner已更改为:javax.swing .JButton [,0,18,41x26,(跳过)]
permanentFocusOwner更改为:null
permanentFocusOwner从:null
permanentFocusOwner更改为:javax.swing.JButton [,41,18,41x26,(skipped)]
(可选部分,关于代码意图)
我的目标是使一些看起来像列表视图的东西,其中条目扩展并在它们获得焦点时显示更多信息(并在它们丢失时折叠回来).展开的视图包含一些其他按钮.
JList似乎不是合适的控件,因为(1)它不允许点击按钮,(2)它的条目具有恒定的高度,而我希望条目在焦点上动态扩展.JTable其编辑模式似乎也不是一个合适的解决方案,至少因为持续的条目大小.
所以我使用JPanel带有垂直框布局的plain 作为容器,并订阅模型更改并手动更新视觉效果.问题是,当我单击按钮时,包含列表项失去焦点.如果焦点不会null暂时改变,我可以检测到焦点仍然在列表项内.
KeyboardFocusManager 正在为大多数属性触发两个事件(根据 beans 规范,它不应该 - 从未找到原因,只是猜测焦点的异步性质可能是原因)
firePropertyChange(someProperty, oldValue, null)
firePropertyChange(someProperty, null, newValue)
Run Code Online (Sandbox Code Playgroud)
要根据 newVaue 执行操作,请等待第二个