Java 如何禁用 JPanel 中的所有组件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19324918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 16:07:16  来源:igfitidea点击:

How to disable all components in a JPanel

javaswingjpanelcomponents

提问by XQEWR

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:

在我的 JPanel 中,我有许多组件,包括其他 JPanel、JLabels、JTextAreas 和 JButtons。因为我想实现一个教程模式,其中出现另一个窗口并且我的主 JPanel 中的所有内容都被禁用,因为新窗口逐一解释了每个“功能”......我想知道如何禁用我内部的所有组件原始JPanel。我知道你可以使用:

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?

但是我不想为我的 JPanel 中的每个组件编写它。我想知道是否可以使用 for 循环或其他方式禁用 JPanel 中的所有组件?

Note: There are also component in nested JPanels, like the order would be

注意:嵌套的 JPanel 中也有组件,就像顺序一样

Main JPanel ---> Nested JPanel ---> Component

主 JPanel ---> 嵌套 JPanel ---> 组件

I also want the Final components to also be disabled...

我还希望最终组件也被禁用......

Thanks! All help is appreciated!

谢谢!感谢所有帮助!

采纳答案by camickr

Check out Disabled Panelfor 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.

一种使用禁用的 GlassPane 类型的方法,另一种递归禁用组件,同时跟踪组件的当前状态,以便以后可以正确启用。

回答by acsadam0404

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).

JPanel 是一个容器。Container 有一个 getComponents() 方法。您应该递归遍历组件树。
如果当前孩子也是一个容器(instanceof),你可以进行另一个递归调用,否则你只需调用 setEnabled(false)。

回答by MadProgrammer

I implemented a solution using JXLayera little while ago, which uses it's lock effect capabilities to provide a "blocking" layer over the container.

JXLayer不久前我实现了一个解决方案,它使用它的锁定效果功能在容器上提供一个“阻塞”层。

It's based on JXLayer 3.xand uses the filters from JHLabsto generate it's "gray scale" effect

它基于JXLayer 3.x并使用来自JHLabs的过滤器来生成它的“灰度”效果

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 LockableUIfor more details

查看LockableUI了解更多详情

回答by Kesavamoorthi

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);
    }
}

回答by SHADOW.NET

Easy fast way :)

简单快捷的方法:)

for (Component cp : yourPanle.getComponents() ){
        cp.setEnabled(false);
 }

回答by Dreamspace President

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.

我只是做了一个小类,它递归地禁用给定容器中的所有内容,然后重新启用之前禁用的每个组件(以相反的顺序)。它还允许从禁用中排除任意组件,这是我添加的一个功能,因为 JLabel 在禁用时看起来不必要地难看。

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);
                    }
                }
            }
        }
    }


}