我有一个方法可以递归启用/禁用JPanel
中的所有组件。还有例外列表。所以我可以做以下
panel1
中的所有组件,但应启用的textfield1, 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不会太混乱......;)
答案 0 :(得分: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);
}
}
}
}
}