2012-06-11 27 views
6

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

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 utilizando JLayer partir de este ejemplo 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 siguiente enlace eventos son en relación con el ratón solamente. ¿Cómo puedo administrar los eventos del teclado?

2) ¿Cómo puedo crear un efecto de "salida gris" en lugar de desenfoque?

+0

Es posible ajustar la visibilidad del panel directamente por el uso de 'panel.setVisible (falso)' –

+0

setVisible (falsa) hace que el componente " invisible "pero en realidad lo necesito todavía visible pero grisáceo". – Randomize

+0

¿Este subproceso ayuda en absoluto? http://stackoverflow.com/a/305551/1417974 –

Respuesta

2

puede superponer toda bloque Container/JComponent

  1. GlassPane por MouseEvents por defecto, pero no del teclado, requiere que consumen todos los KeyEvents de ToolKit

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

  3. no se puede ver la (s) razón (es) por la 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(); 
    } 
} 
+0

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

+0

1) no hay problema puesto allí JLabel.setOpaque (falso) y coloque algunos Color (int, int, int, alpa), 2) JXLabel no es librerías externas, este es un proyecto personal aceptado como JLayer, 3) ponga JLabel en el (mismo que en el primer punto) JViewPort (Espero que JTable esté en JScrollPane) 4) puedes revisar mis publicaciones GlassPane y JViewport etiquetados – mKorbel

+0

Estoy intentando con JLayer y he resuelto parcialmente el problema. Por favor mira mi pregunta reeditada. – Randomize

40

Requiere una llamada recursiva.

Disable All In Container

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

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

+0

También tiene el problema de, si algunos de los componentes en el contenedor se habilitaron y otros se desactivaron, entonces todos se establecerán en el mismo estado habilitado, por ejemplo: No se puede hacer una habilitación, y luego deshacerla trivialmente. – user1062589

+1

declare enableComponents (...) estático. muy buena función de utilidad – Exceptyon

5

que utiliza 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); 
    } 
} 
Cuestiones relacionadas