Java Swing: habilitar/deshabilitar todos los componentes en JPanel

Tengo un JPanel que contiene una JToolbar (incluidos algunos botones sin texto) y una JTable y necesito habilitar/deshabilitar (hacer que no se pueda hacer clic en los widgets internos). Intenté esto:

 JPanel panel = ....;
 for (Component c : panel.getComponents()) c.setEnabled(enabled);

pero no funciona ¿Existe una solución mejor y más genérica para habilitar/deshabilitar todos los componentes internos en un JPanel?

He resuelto parcialmente mi problema usando JLayer a partir del ejemplo aquí 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();
    }
  }

}

Todavía tengo 2 problemas:

  1. En el enlace de arriba, los eventos son relativos solo al mouse. ¿Cómo puedo gestionar los eventos del teclado?

  2. ¿Cómo puedo crear un efecto de "desaparición gris" en lugar de desenfoque?

preguntado el 11 de junio de 12 a las 19:06

Puede configurar la visibilidad del panel directamente usando panel.setVisible(false) -

setVisible (falso) hace que el componente sea "invisible", pero en realidad lo necesito aún visible pero atenuado. -

¿Este hilo ayuda en absoluto? stackoverflow.com/a/305551/1417974 -

Ya revisé ese hilo y apliqué algo sin éxito real. -

¿No es hora de que aceptes una respuesta sobre esto? -

4 Respuestas

Requiere una llamada recursiva.

Deshabilitar todo en contenedor

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

Respondido el 11 de junio de 12 a las 20:06

Gracias, esa solución está muy cerca de la mía. Pero tiene el mismo problema: tengo un JTable y si aplica setEnabled (falso) en él, no se puede hacer clic en la tabla pero no está "atenuada" frente a los componentes restantes. - Randomize

También tiene el problema de que, si algunos de los componentes en el contenedor estaban habilitados y otros deshabilitados, todos se establecerán en el mismo estado habilitado, por ejemplo: no puede habilitar y luego deshacer trivialmente. - user1062589

declarar enableComponents(...) estático. muy buena función de utilidad - Exceptionon

Usé la siguiente función:

void setPanelEnabled(JPanel panel, Boolean isEnabled) {
    panel.setEnabled(isEnabled);

    Component[] components = panel.getComponents();

    for(int i = 0; i < components.length; i++) {
        if(components[i].getClass().getName() == "javax.swing.JPanel") {
            setPanelEnabled((JPanel) components[i], isEnabled);
        }

        components[i].setEnabled(isEnabled);
    }
}

Respondido el 09 de Septiembre de 15 a las 15:09

puedes superponer todo Container / JComponent

  1. GlassPane bloquear por defecto MouseEvents, pero no Keyboard, requiere consumir todos los keyevents de ToolKit

  2. JLayer (Java7) basado en JXLayer (Java6)

  3. no puedo ver las razones por las que no funciona para usted

enter image description here

enter image description here

enter image description here

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

public class AddComponentsAtRuntime {

    private JFrame f;
    private JPanel panel;
    private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack;

    public AddComponentsAtRuntime() {
        JButton b = new JButton();
        //b.setBackground(Color.red);
        b.setBorder(new LineBorder(Color.black, 2));
        b.setPreferredSize(new Dimension(600, 20));
        panel = new JPanel(new GridLayout(0, 1));
        panel.add(b);
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(panel, "Center");
        f.add(getCheckBoxPanel(), "South");
        f.setLocation(200, 200);
        f.pack();
        f.setVisible(true);
    }

    private JPanel getCheckBoxPanel() {
        checkValidate = new JCheckBox("validate");
        checkValidate.setSelected(false);
        checkReValidate = new JCheckBox("revalidate");
        checkReValidate.setSelected(true);
        checkRepaint = new JCheckBox("repaint");
        checkRepaint.setSelected(true);
        checkPack = new JCheckBox("pack");
        checkPack.setSelected(true);
        JButton addComp = new JButton("Add New One");
        addComp.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JButton b = new JButton();
                //b.setBackground(Color.red);
                b.setBorder(new LineBorder(Color.black, 2));
                b.setPreferredSize(new Dimension(400, 10));
                panel.add(b);
                makeChange();
                System.out.println(" Components Count after Adds :" + panel.getComponentCount());
            }
        });
        JButton removeComp = new JButton("Remove One");
        removeComp.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int count = panel.getComponentCount();
                if (count > 0) {
                    panel.remove(0);
                }
                makeChange();
                System.out.println(" Components Count after Removes :" + panel.getComponentCount());
            }
        });
        JButton disabledComp = new JButton("Disabled All");
        disabledComp.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Component c : panel.getComponents()) {
                    c.setEnabled(false);
                }
            }
        });
        JButton enabledComp = new JButton("Enabled All");
        enabledComp.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (Component c : panel.getComponents()) {
                    c.setEnabled(true);
                }
            }
        });
        JPanel panel2 = new JPanel();
        panel2.add(checkValidate);
        panel2.add(checkReValidate);
        panel2.add(checkRepaint);
        panel2.add(checkPack);
        panel2.add(addComp);
        panel2.add(removeComp);
        panel2.add(disabledComp);
        panel2.add(enabledComp);
        return panel2;
    }

    private void makeChange() {
        if (checkValidate.isSelected()) {
            panel.validate();
        }
        if (checkReValidate.isSelected()) {
            panel.revalidate();
        }
        if (checkRepaint.isSelected()) {
            panel.repaint();
        }
        if (checkPack.isSelected()) {
            f.pack();
        }
    }

    public static void main(String[] args) {
        AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime();
    }
}

Respondido el 11 de junio de 12 a las 20:06

gracias por las respuestas múltiples: 1) GlassPane es interesante aunque no sé cómo obtener un efecto borroso o gris. 2) Estoy trabajando con Java 6 y no quiero (por el momento) usar bibliotecas externas. 3) Esta solución tiene problemas con JTable. - Randomize

1) no hay problema, coloque JLabel.setOpaque (falso) y coloque algo de Color (int, int, int, alpa), 2) JXLabel no son bibliotecas externas, este es un proyecto personal aceptado como JLayer, 3) coloque JLabel en el (igual que en el primer punto) JViewPort (espero que JTable esté en JScrollPane) 4) puede revisar mis publicaciones GlassPane y JViewport etiquetadas - mKorbel

Estoy probando con JLayer y resolví parcialmente el problema. Por favor, mire mi pregunta reeditada. - Randomize

@Kesavamoorthi si quieres hacerlo más general:

void setPanelEnabled(java.awt.Container cont, Boolean isEnabled) {
    cont.setEnabled(isEnabled);

    java.awt.Component[] components = cont.getComponents();

    for (int i = 0; i < components.length; i++) {
        if (components[i] instanceof java.awt.Container) {
            setPanelEnabled((java.awt.Container) components[i], isEnabled);
        }
        components[i].setEnabled(isEnabled);
    }
}

Respondido 15 Oct 18, 10:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.