2

我有一种方法可以递归地启用/禁用JPanel. 还有例外列表。所以我可以做以下

  • 禁用panel1textfield1, textfield3应启用的所有组件。
  • 启用所有组件,panel2除了button2, label3应该禁用的组件。

这是一个 SSCCE 正是这样做的:

import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        final JPanel panel = new JPanel(new GridLayout(3, 3));

        final JTextField textfield = new JTextField("asdf");
        final JButton button = new JButton("asdf");
        final JCheckBox checkbox = new JCheckBox("asdf");
        final JSpinner spinner = new JSpinner(new SpinnerNumberModel(1, 1, 100, 1));
        final JLabel label = new JLabel("asdf");

        panel.add(textfield);
        panel.add(button);
        panel.add(checkbox);
        panel.add(spinner);
        panel.add(label);
        // fill in some random stuff
        for (int i = 0; i < 4; i++)
            panel.add(new JLabel("asdf"));

        frame.setContentPane(panel);
        frame.setSize(300, 100);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        new Thread(new Runnable() {
            @Override
            public void run() {
                boolean toggle = true;
                while (true) {
                    toggle = !toggle;
                    Set<Component> enableList = new HashSet<Component>();
                    Set<Component> disableList = new HashSet<Component>();
                    enableList.add(textfield);
                    enableList.add(spinner);
                    disableList.add(checkbox);
                    setEnableAllRec(panel, toggle, disableList, enableList);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {}
                }
            }
        }).start();
        frame.setVisible(true);
    }

    public static void setEnableAllRec(Container root, boolean defaultState, Set<Component> disableList, Set<Component> enableList) {
        if (root == null) return;
        for (Component c : root.getComponents()) {
            if (disableList != null && disableList.contains(c)) {
                c.setEnabled(false);
                disableList.remove(c);
            } else if (enableList != null && enableList.contains(c)) {
                c.setEnabled(true);
                enableList.remove(c);
            } else c.setEnabled(defaultState);
            if (c instanceof Container) setEnableAllRec((Container) c, defaultState, disableList, enableList);
        }
    }
}

SSCCE 每秒将所有组件设置为交替启用/禁用。除了一些应该始终启用的组件和一些应该始终禁用的组件。除了JSpinner. 它被检测为组件,但无法在列表中找到(因此不作为特殊情况处理)。我尝试过的所有其他摆动组件都按预期工作。

你能告诉我有什么问题JSpinner吗?

我希望 SSCCE 不会太混乱...... ;)

4

1 回答 1

3

仅仅因为 JSpinner 包含其他组件,例如 2 个按钮和一个编辑器(请参阅 的代码javax.swing.plaf.basic.BasicSpinnerUI),并且您递归地访问所有容器,因此,也在JSpinner.

顺便说一句,您的线程违反了 Swing-EDT。你应该在一个Swing Timer

解决方案很简单:

import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        final JPanel panel = new JPanel(new GridLayout(3, 3));

        final JTextField textfield = new JTextField("asdf");
        final JButton button = new JButton("asdf");
        final JCheckBox checkbox = new JCheckBox("asdf");
        final JSpinner spinner = new JSpinner(new SpinnerNumberModel(1, 1, 100, 1));
        final JLabel label = new JLabel("asdf");

        panel.add(textfield);
        panel.add(button);
        panel.add(checkbox);
        panel.add(spinner);
        panel.add(label);
        // fill in some random stuff
        for (int i = 0; i < 4; i++) {
            panel.add(new JLabel("asdf"));
        }

        frame.setContentPane(panel);
        frame.setSize(300, 100);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        new Thread(new Runnable() {
            @Override
            public void run() {
                boolean toggle = true;
                while (true) {
                    toggle = !toggle;
                    Set<Component> enableList = new HashSet<Component>();
                    Set<Component> disableList = new HashSet<Component>();
                    enableList.add(textfield);
                    enableList.add(spinner);
                    disableList.add(checkbox);
                    setEnableAllRec(panel, toggle, disableList, enableList);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                }
            }
        }).start();
        frame.setVisible(true);
    }

    public static void setEnableAllRec(Container root, boolean defaultState, Set<Component> disableList, Set<Component> enableList) {
        if (root == null) {
            return;
        }
        for (Component c : root.getComponents()) {
            if (disableList != null && disableList.contains(c)) {
                c.setEnabled(false);
                disableList.remove(c);
            } else if (enableList != null && enableList.contains(c)) {
                c.setEnabled(true);
                enableList.remove(c);
            } else {
                c.setEnabled(defaultState);
                if (c instanceof Container) {
                    setEnableAllRec((Container) c, defaultState, disableList, enableList);
                }
            }
        }
    }
}
于 2012-12-12T15:59:23.487 回答