【问题标题】:Toggle "enabled" state of a large number of components in a Java Swing applicaiton在 Java Swing 应用程序中切换大量组件的“启用”状态
【发布时间】:2013-10-28 09:57:20
【问题描述】:

我正在使用 Java swing 为我的 Java 游戏制作关卡编辑器。

其中一个功能是有一个可切换按钮来打开和关闭游戏以测试关卡。游戏在 jpanel 中运行,然后再次单击按钮取消切换,它会关闭游戏。

我只希望用户能够在游戏未运行时更改摇摆应用程序中的内容或按下按钮,当游戏运行时,我将焦点设置到游戏组件。他们应该能够在摇摆应用程序中按下的唯一按钮是用于关闭游戏的切换按钮。

问题是,我想不出一个好的方法来做到这一点。使用递归函数,我可以轻松循环并找到所有组件并执行 setEnabled(false),但是当游戏重新关闭时,它无法知道之前的启用状态是什么(以及其他问题,例如其他组件响应setEnabled 在其他组件上被调用)

我认为我真正需要的只是一种在游戏运行时直接“杀死”用户输入到 Swing 应用程序的方法。但最好是再次单击切换按钮以返回应用程序的状态,并且在 Jpanel 中运行的游戏需要能够有焦点...

有没有办法在没有大量“组织”代码来管理 Swing 应用程序中的组件的情况下完成这种事情?

【问题讨论】:

    标签: java swing jcomponent


    【解决方案1】:

    您可以像这样将所有内容都放在地图中。

    class ComponentState { 
     private JComponent component;
     private bool on;
     // Getters & Setters
    }
    
    private Map<String, ComponentState> components = new HashMap<>();
    

    为了向您的游戏添加新组件:

    components.add("startbutton", new ComponentState(new JButton, true));
    

    然后将所有组件添加到您的屏幕:

    for(String key : components.KeySet()) {
     ComponentState comp = components.get(key);
     if(comp.isOn()) { this.add(comp.getComponent()) };
    }
    

    并禁用/激活组件:

    components.get("myActivatedComponent").disable(); // disable is a self defined method
    

    【讨论】:

    • 您应该使用 Map,只要您的自定义组件使用默认的 hashcode() 实现(返回内存地址)。这将减少分配的微小对象的数量(布尔类使用实习,因此只有两个实例)。
    • @AurélienRibon:那么您将无法专门检索组件。您将如何从 Map 返回开始按钮?
    • 您的开始按钮是在某处定义的,因此您应该在某处引用它。但正如 OP 所建议的那样,该地图旨在用于递归函数。
    • 请参阅我的答案以获得澄清。
    • 是的,如果你在类级别有对组件的引用,那么你可以这样做,但我专门构建了这个解决方案来省略它。删除 ComponentState 类并使用您的解决方案是可能的,但不一定是可取的。这是过早的优化,而且只是非常轻微。 OP 并不意味着递归,因为他建议的不是递归的。
    【解决方案2】:

    您需要一个将每个组件设置为禁用状态的disableAll() 方法,以及一个将每个组件状态重置回其先前状态的resetAll() 方法。当您禁用它时,您需要保存每个组件的状态,以便能够在之后恢复它。这将占用O(n) 空间。

    private final Map<JComponent, Boolean> components = new HashMap<JComponent, Boolean>();
    
    public void disableAll(JComponent root) {
        components.put(root, root.isEnabled());
        root.setEnabled(false);
    
        for (int i=0, n=root.getComponentCount(); i<n; i++) {
            JComponent child = (JComponent) root.getComponentAt(i);
            disableAll(child);
        }
    }
    
    public void resetAll(JComponent root) {
        boolean status = components.get(root);
        root.setEnabled(status);
    
        for (int i=0, n=root.getComponentCount(); i<n; i++) {
            JComponent child = (JComponent) root.getComponentAt(i);
            resetAll(child);
        }
    }
    

    【讨论】:

    • 我明白了,这就是您解释递归的方式。很公平,像这样它确实是递归的。这是一种略有不同的方法,我想这取决于您希望如何引用组件:从 Map 中的字段或键。
    【解决方案3】:

    另一种选择是使用GlassPane 并“灰显”一个组件区域。您还必须捕获并忽略窗格中您不希望用户点击的区域的点击。

    通过此处的 Java 教程中的示例查看更多信息:http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html

    这篇文章也可能会有所帮助: https://weblogs.java.net/blog/alexfromsun/archive/2006/09/a_wellbehaved_g.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      • 2017-07-10
      • 1970-01-01
      • 2017-09-02
      相关资源
      最近更新 更多