2012-06-11 11 views
6

Ho un JPanel che contiene una barra di JTool (compresi alcuni pulsanti senza testo) e una tabella di controllo e devo abilitare/disabilitare (rendere i widget interni non selezionabili). Ho provato questo:Java Swing: attivazione/disattivazione di tutti i componenti in JPanel

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

ma non funziona. Esiste una soluzione migliore e più generica per abilitare/disabilitare tutti i componenti interni in un JPanel?

ho parzialmente risolto il problema utilizzando JLayer partendo dall'esempio qui 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(); 
    } 
    } 

} 

ho ancora 2 problemi:

1) nel link qui eventi sono relativi solo mouse. Come posso gestire gli eventi della tastiera?

2) Come posso creare un effetto "grigio" al posto della sfocatura?

+0

È possibile impostare la visibilità del pannello direttamente utilizzando 'panel.setVisible (false)' –

+0

setVisible (false) rende la componente " invisibile "ma in realtà ne ho bisogno ancora visibile ma in grigio. – Randomize

+0

questo thread non aiuta affatto? http://stackoverflow.com/a/305551/1417974 –

risposta

2

è possibile sovrapporre intero blocco Container/JComponent

  1. GlassPane da MouseEvents di default, ma non la tastiera, tenuti consumano tutti keyevents da ToolKit

  2. JLayer (Java7) sulla base di JXLayer (java6)

  3. non riesco a vedere i motivi per cui non funziona per voi

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

grazie per le risposte multiple: 1) GlassPane è interessante perché non so come ottenere un effetto sfocato o sfumato. 2) Sto lavorando con Java 6 e non voglio (per il momento) usare librerie esterne. 3) Questa soluzione ha problemi con JTable. – Randomize

+0

1) nessun problema messo lì JLabel.setOpaque (false) e metti un po 'di colore (int, int, int, alpa), 2) JXLabel non è librerie esterne, questo è un progetto personale accettato come JLayer, 3) inserisci JLabel allo stesso (come nel primo punto) JViewPort (Spero che JTable sia in JScrollPane) 4) Puoi controllare i miei post GlassPane e JViewport taggati – mKorbel

+0

Sto provando con JLayer e ho risolto parzialmente il problema. Per favore guarda la mia domanda modificata. – Randomize

40

Richiede una chiamata ricorsiva.

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

Grazie a questa soluzione è molto vicino alla mia soluzione. Ma ha lo stesso problema: ho un JTable e se applichi setEnabled (false) su di esso, la tabella non diventa cliccabile ma non è "grigiata" in senso opposto ai componenti rimanenti. – Randomize

+0

Ha anche il problema di, se alcuni dei componenti del contenitore sono stati abilitati e altri disabilitati, saranno tutti impostati sullo stesso stato abilitato, ad esempio: non è possibile eseguire un'abilitazione e quindi annullarla banalmente. – user1062589

+1

dichiarare enableComponents (...) statico. funzione di utilità molto bella – Exceptyon

5

ho usato la seguente funzione:

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