可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In my JPanel I have many components, including other JPanels, JLabels, JTextAreas, and JButtons. Becuase I want to implement a tutorial mode where another window appears and everything in my main JPanel is disabled as the new window explains each 'feature' one by one... I want a to know how to disable all the components that are inside my origiinal JPanel. I know you can use:
component.setEnabled(false);
But I don't want to write it for each component in my JPanel. I would like to know if it's possible to disable ALL components within my JPanel with a for loop or something?
Note: There are also component in nested JPanels, like the order would be
Main JPanel ---> Nested JPanel ---> Component
I also want the Final components to also be disabled...
Thanks! All help is appreciated!
回答1:
Check out Disabled Panel for a couple of solutions.
One uses a disabled GlassPane type of approach and the other recursively disables components while keep track of the components current state so it can be enable properly later.
回答2:
I used the following function:
void setPanelEnabled(JPanel panel, Boolean isEnabled) {
panel.setEnabled(isEnabled);
Component[] components = panel.getComponents();
for (Component component : components) {
if (component instanceof JPanel) {
setPanelEnabled((JPanel) component, isEnabled);
}
component.setEnabled(isEnabled);
}
}
回答3:
JPanel is a Container. Container has a getComponents() method. You should traverse in the component tree recursively.
If the current child is a Container too (instanceof), you can make another recursive call, else you just call setEnabled(false).
回答4:
I implemented a solution using JXLayer
a little while ago, which uses it's lock effect capabilities to provide a "blocking" layer over the container.
It's based on JXLayer 3.x and uses the filters from JHLabs to generate it's "gray scale" effect
import com.jhlabs.image.GrayscaleFilter;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.LayoutManager;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.QualityHints;
import org.jdesktop.jxlayer.plaf.BetterBufferedImageOpEffect;
import org.jdesktop.jxlayer.plaf.LayerUI;
import org.jdesktop.jxlayer.plaf.ext.LockableUI;
public class CoreXPane extends JPanel {
private JXLayer<JPanel> layer;
private FadedLockUI fadedLockUI;
private JPanel pnlBody;
public CoreXPane(LayoutManager layout) {
super.setLayout(new BorderLayout());
super.addImpl(getLayer(), BorderLayout.CENTER, 0);
setLayout(layout);
}
public CoreXPane() {
this(new BorderLayout());
}
@Override
public void setEnabled(boolean enabled) {
getLockUI().setLocked(!enabled);
getBodyPane().setEnabled(enabled);
super.setEnabled(enabled);
}
@Override
protected void addImpl(Component comp, Object constraints, int index) {
getBodyPane().add(comp, constraints, index);
}
@Override
public void remove(int index) {
getBodyPane().remove(index);
}
@Override
public void removeAll() {
getBodyPane().removeAll();
}
protected FadedLockUI getLockUI() {
if (fadedLockUI == null) {
fadedLockUI = new FadedLockUI();
}
return fadedLockUI;
}
@Override
public void invalidate() {
getLockUI().invalidate();
super.invalidate();
}
@Override
public void revalidate() {
getLockUI().revalidate();
super.revalidate();
}
@Override
public void repaint() {
getLockUI().repaint();
super.repaint();
}
protected void getLayers(List<LayerUI> layers) {
layers.add(getLockUI());
}
protected JXLayer<JPanel> getLayer() {
if (layer == null) {
List<LayerUI> layers = new ArrayList<LayerUI>(4);
getLayers(layers);
JComponent wrapper = getBodyPane();
for (LayerUI ui : layers) {
wrapper = new JXLayer(wrapper, ui);
}
layer = (JXLayer<JPanel>) wrapper;
}
return layer;
}
@Override
public void setLayout(LayoutManager mgr) {
getBodyPane().setLayout(mgr);
}
@Override
public LayoutManager getLayout() {
return getBodyPane().getLayout();
}
public JPanel getBodyPane() {
if (pnlBody == null) {
pnlBody = new JPanel();
pnlBody.setLayout(new BorderLayout());
}
return pnlBody;
}
@Override
public void setOpaque(boolean isOpaque) {
super.setOpaque(isOpaque);
getBodyPane().setOpaque(isOpaque);
}
public static class FadedLockUI extends LockableUI {
public static Map<RenderingHints.Key, Object> mapRenderHints = new QualityHints();
public FadedLockUI() {
setLockedEffects(new BufferedImageOpEffect(new GrayscaleFilter()));
mapRenderHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); // okay
mapRenderHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // bad
mapRenderHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); // okay
mapRenderHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
mapRenderHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
mapRenderHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
mapRenderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
}
@Override
protected Map<RenderingHints.Key, Object> getRenderingHints(JXLayer<? extends JComponent> l) {
return mapRenderHints;
}
public void repaint() {
setDirty(true);
}
public void invalidate() {
setDirty(true);
}
public void revalidate() {
setDirty(true);
}
}
}
Take a look at LockableUI for more details
回答5:
Easy fast way :)
for (Component cp : yourPanle.getComponents() ){
cp.setEnabled(false);
}
回答6:
I just made a little class that disables everything inside a given Container recursively and later re-enables every Component that was disabled earlier (in the opposite order). It also allows to exclude arbitrary Components from disabling, a feature I added because JLabels look unnecessarily ugly when disabled.
Works like a charm. Since the problem comes up often enough, and I happened to see this post earlier today, here's the class:
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* Purpose: To recursively disable (and later re-enable) all components of a container, e.g. if you want to clearly show
* that a program is busy or if you want to prevent clicks and other inputs that piled up meanwhile to affect a window
* once the program becomes responsive again. Though the solution for that would be simpler: Just disable the window and
* then, in a SwingUtilities.invokeLater(), re-enable it. This makes sure that before this happens, all input events are
* eaten.
*/
final public class EverythingDisablerAndReenabler { // v[1, 2016-12-05 14!30 UTC] by dreamspace-president.com
final private Container rootContainerForWhatShouldBeDisabled;
final private Class<?>[] componentClassesToBeIgnored;
final private List<Component> componentsToReenable = new ArrayList<>();
private boolean disableHasBeenCalled = false; // Order is strictly upheld via IllegalStateException!
/**
* @param rootContainerForWhatShouldBeDisabled NOT NULL! The Container whose components are to be recursively
* disabled. The container itself will not be disabled.
* @param componentClassesToBeIgnored null or an array of classes (e.g. containing JLabel.class) that
* should be excluded from disabling. Adding a Container here does not
* affect the recursive process.
* @throws IllegalArgumentException if the container argument is null. In case someone wonders why I don't use
* {@link NullPointerException} here: Null can be a perfectly legal argument in
* other places, but here, it is not. If an argument does not check out, the choice
* of Exception, of course, is IllegalArgument, not NullPointer.
*/
public EverythingDisablerAndReenabler(final Container rootContainerForWhatShouldBeDisabled, final Class<?>[] componentClassesToBeIgnored) {
if (rootContainerForWhatShouldBeDisabled == null) {
throw new IllegalArgumentException();
}
this.rootContainerForWhatShouldBeDisabled = rootContainerForWhatShouldBeDisabled;
this.componentClassesToBeIgnored = componentClassesToBeIgnored;
}
/**
* Disables everything recursively, except the excluded types.
*
* @throws IllegalStateException if called twice in a row.
*/
public void disable() {
if (disableHasBeenCalled) {
throw new IllegalStateException();
}
disableHasBeenCalled = true;
componentsToReenable.clear();
disableEverythingInsideThisHierarchically(rootContainerForWhatShouldBeDisabled);
}
/**
* @throws IllegalStateException if called twice in a row or if disable() had not been called yet.
*/
public void reenable() {
if (!disableHasBeenCalled) {
throw new IllegalStateException();
}
disableHasBeenCalled = false;
for (int i = componentsToReenable.size() - 1; i >= 0; i--) {
componentsToReenable.get(i).setEnabled(true);
}
componentsToReenable.clear();
}
private void disableEverythingInsideThisHierarchically(final Container container) {
final Component[] components = container.getComponents();
for (Component component : components) {
if (component != null) {
// RECURSION FIRST
if (component instanceof Container) {
disableEverythingInsideThisHierarchically((Container) component);
}
// AND THEN DEAL WITH THE ELEMENTS
if (component.isEnabled()) {
boolean found = false;
if (componentClassesToBeIgnored != null) {
for (Class<?> cls : componentClassesToBeIgnored) {
if (component.getClass() == cls) {
found = true;
break;
}
}
}
if (!found) {
component.setEnabled(false);
componentsToReenable.add(component);
}
}
}
}
}
}