Java Swing: Enabling/Disabling all components in JPanel

java, jpanel, swing

Solution

It requires a recursive call.

import java.awt.*;
import javax.swing.*;

public class DisableAllInContainer {

    public void enableComponents(Container container, boolean enable) {
        Component[] components = container.getComponents();
        for (Component component : components) {
            component.setEnabled(enable);
            if (component instanceof Container) {
                enableComponents((Container)component, enable);
            }
        }
    }

    DisableAllInContainer() {
        JPanel gui = new JPanel(new BorderLayout());

        final JPanel container = new JPanel(new BorderLayout());
        gui.add(container, BorderLayout.CENTER);

        JToolBar tb = new JToolBar();
        container.add(tb, BorderLayout.NORTH);
        for (int ii=0; ii<3; ii++) {
            tb.add(new JButton("Button"));
        }

        JTree tree = new JTree();
        tree.setVisibleRowCount(6);
        container.add(new JScrollPane(tree), BorderLayout.WEST);

        container.add(new JTextArea(5,20), BorderLayout.CENTER);

        final JCheckBox enable = new JCheckBox("Enable", true);
        enable.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent ae) {
                enableComponents(container, enable.isSelected());
            }
        });
        gui.add(enable, BorderLayout.SOUTH);

        JOptionPane.showMessageDialog(null, gui);
    }

    public static void main(String[] args)  {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                new DisableAllInContainer();
            }
        });
    }}

Problem

I have a JPanel which contains a JToolbar (including few buttons without text) and a JTable and I need to enable/disable (make internal widgets not clickable). I tried this: ``` JPanel panel = ....; for (Component c : panel.getComponents()) c.setEnabled(enabled); ``` but it doesn't work. Is there a better and more generic solution to enable/disable all internal components in a JPanel? I have partially solved my problem using JLayer starting from the example here http://docs.oracle.com/javase/tutorial/uiswing/misc/jlayer.html: ``` layer = new JLayer<JComponent>(myPanel, new BlurLayerUI(false)); ..... ((BlurLayerUI)layer.getUI()).blur(...); // switch blur on/off class BlurLayerUI extends LayerUI<JComponent> { private BufferedImage mOffscreenImage; private BufferedImageOp mOperation; private boolean blur; public BlurLayerUI(boolean blur) { this.blur = blur; float ninth = 1.0f / 9.0f; float[] blurKernel = { ninth, ninth, ninth, ninth, ninth, ninth, ninth, ninth, ninth }; mOperation = new ConvolveOp( new Kernel(3, 3, blurKernel), ConvolveOp.EDGE_NO_OP, null); } public void blur(boolean blur) { this.blur=blur; firePropertyChange("blur", 0, 1); } @Override public void paint (Graphics g, JComponent c) { if (!blur) { super.paint (g, c); return; } int w = c.getWidth(); int h = c.getHeight(); if (w == 0 || h == 0) { return; } // Only create the offscreen image if the one we have // is the wrong size. if (mOffscreenImage == null || mOffscreenImage.getWidth() != w || mOffscreenImage.getHeight() != h) { mOffscreenImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); } Graphics2D ig2 = mOffscreenImage.createGraphics(); ig2.setClip(g.getClip()); super.paint(ig2, c); ig2.dispose(); Graphics2D g2 = (Graphics2D)g; g2.drawImage(mOffscreenImage, mOperation, 0, 0); } @Override public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) { if ("blur".equals(pce.getPropertyName())) { l.repaint(); } } } ``` I still have 2 problems: In the link above events are relative to mouse only. How can I manage the keyboard events? How can I create a "gray out" effect in place of blur?

Original source

Related problems