Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检测具有多个子组件的focuslost_Java_Swing_User Interface_Focus - Fatal编程技术网

Java 检测具有多个子组件的focuslost

Java 检测具有多个子组件的focuslost,java,swing,user-interface,focus,Java,Swing,User Interface,Focus,我想创建一个可扩展的面板(为特定任务容纳多个UI元素)。面板可以通过用户操作展开,只要面板中的任何子组件都有焦点,面板就应该保持展开状态。当用户将焦点放在面板外某个位置时,它应该关闭 有简单的方法吗 当焦点移出任何子组件时,获取focuslost事件 或者询问面板的任何子组件是否仍然具有焦点 或者我需要在每个子组件上注册/检查焦点(-events)? (因为这应该是一个通用的面板,我需要一种独立于子组件特定层次结构的通用方法。)根据,是在当前的KeyboardFocusManager上安装一

我想创建一个可扩展的面板(为特定任务容纳多个UI元素)。面板可以通过用户操作展开,只要面板中的任何子组件都有焦点,面板就应该保持展开状态。当用户将焦点放在面板外某个位置时,它应该关闭

有简单的方法吗

  • 当焦点移出任何子组件时,获取focuslost事件
  • 或者询问面板的任何子组件是否仍然具有焦点
或者我需要在每个子组件上注册/检查焦点(-events)?
(因为这应该是一个通用的面板,我需要一种独立于子组件特定层次结构的通用方法。)

根据,是在当前的
KeyboardFocusManager
上安装一个
PropertyChangeListener
。例如:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Main {
    
    private static void createAndShowGUI() {
        
        final int rows = 5, cols = 5;
        final JPanel focusables = new JPanel(new GridLayout(0, cols, 10, 10));
        for (int row = 0; row < rows; ++row)
            for (int col = 0; col < cols; ++col)
                focusables.add(new JTextField("Focusable", 10));
        
        final JPanel nonFocusable = new JPanel(); //FlowLayout.
        nonFocusable.add(new JTextField("Click here to change focus"));
         
        final JPanel contents = new JPanel(new BorderLayout());
        contents.add(focusables, BorderLayout.CENTER);
        contents.add(nonFocusable, BorderLayout.LINE_END);
        
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener("focusOwner", new PropertyChangeListener() {
            @Override
            public void propertyChange(final PropertyChangeEvent evt) {
                final Object newValue = evt.getNewValue();
                if (newValue instanceof Component
                        && SwingUtilities.isDescendingFrom((Component) newValue, focusables)) //If 'focusables' is a parent of newValue...
                    focusables.setBackground(Color.GREEN); //Then focus is back on our components...
                else
                    focusables.setBackground(Color.RED); //Else the focus is not on our components (it may even be another application).
            }
        });
        
        final JFrame frame = new JFrame("Multi focus lost");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(contents);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(Main::createAndShowGUI);
    }
}
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Component;
导入java.awt.GridLayout;
导入java.awt.KeyboardFocusManager;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JTextField;
导入javax.swing.SwingUtilities;
公共班机{
私有静态void createAndShowGUI(){
最终int行=5,cols=5;
最终JPanel焦点值=新JPanel(新网格布局(0,cols,10,10));
对于(int行=0;行<行;++行)
for(int col=0;col
根据教程:

每次涉及焦点的更改都会通知属性更改侦听器

如何使用上述示例:

  • 运行它,您可以在每个
    JTextField
    中单击以获得焦点
  • 如果当前聚焦的
    JTextField
    具有我们指定的父
    组件(在本例中,该组件是所需
    JTextField
    s的父
    JPanel
    ,名为
    focusables
    ),则该父项的背景色变为绿色,否则为红色。但是你显然可以实现你的逻辑,而不是改变背景颜色
  • 上述示例的工作原理:

  • 我们在当前的
    KeyboardFocusManager
    上为属性
    focusOwner
    安装
    PropertyChangeListener
    ,只有当应用程序中的任何
    组件更改其focusOwner属性时(即更改聚焦的
    组件
    触发此类事件),我们才会收到通知。我们可以安装一个
    PropertyChangeListener
    ,这样我们就可以得到各种事件的通知,但是
    focusOwner
    是我们唯一感兴趣的,所以我们会让系统知道。有关可按焦点事件跟踪的所有属性的列表,请滚动至
  • PropertyChangeListener
    实现中,我们只需要检查新的焦点所有者是否具有其父级的
    focusables
    面板。我们可以通过从焦点所有者向上遍历
    组件
    层次结构来检查这一点,或者只需调用
    SwingUtilities#isdescingdrom
    ,这是一种方便的方法。如果我们正在侦听所有焦点事件,那么我们还必须手动筛选属性
    focusOwner
    (通过检查
    propertychangevent#getPropertyName
    返回该属性)
  • 请注意,当我们离开应用程序时,所需的
    组件的焦点会丢失(但当我们返回时会返回)

    还要注意的是,为了简单起见,
    组件
    s在上述示例中的层次结构仅为一级深度(即所需的可聚焦
    组件
    s是
    可聚焦
    面板的直接子级),但我们可以将其更改为我们想要的任何级别深度,只要所需的
    组件
    s在其路径上都具有相同的父级(必须与非所需组件的父级不同)


    我能想到的唯一例外是,如果您通常有混合的父
    容器
    s,例如
    JPanel
    s,它们有一个期望的
    组件和一个非期望的组件作为直接子级。在这种情况下,您必须检查每个
    组件