2012-06-11 12 views
6

Mam JPanel, który zawiera JToolbar (w tym kilka przycisków bez tekstu) i JTable i muszę włączyć/wyłączyć (uniemożliwić kliknięcie wewnętrznych widgetów). Próbowałem tego:Java Swing: Włączanie/wyłączanie wszystkich składników w JPanel

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

ale to nie działa. Czy istnieje lepsze i bardziej ogólne rozwiązanie umożliwiające włączanie/wyłączanie wszystkich wewnętrznych komponentów w JPanelu?

mam częściowo rozwiązać mój problem za pomocą JLayer zaczynając od przykładu tutaj 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(); 
    } 
    } 

} 

nadal mam 2 problemy:

1) w linku powyżej zdarzeń są względne tylko myszy. Jak mogę zarządzać wydarzeniami na klawiaturze?

2) Jak mogę utworzyć efekt "szarego" zamiast rozmycia?

+0

Można ustawić widoczność panelu bezpośrednio za pomocą 'panel.setVisible (false)' –

+0

setVisible (fałsz) sprawia, że ​​komponent " niewidzialny ", ale w rzeczywistości potrzebuję go wciąż widocznego, ale szarego. – Randomize

+0

robi w ogóle tę pomoc? http://stackoverflow.com/a/305551/1417974 –

Odpowiedz

2

można nałożyć cały Container/JComponent

  1. GlassPane blok domyślnie MouseEvents, ale nie klawiatura, wymagane spożywać wszystkie keyevents z ToolKit

  2. JLayer (Java7) na podstawie JXLayer (java6)

  3. nie widzę powodu (ów) dlaczego nie działa dla Ciebie

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

dzięki za wiele odpowiedzi: 1) GlassPane jest interesujący, bo nie wiem, jak uzyskać efekt rozmycia lub szarości. 2) Pracuję z Javą 6 i nie chcę (na razie) korzystać z zewnętrznych bibliotek. 3) To rozwiązanie ma problemy z JTable. – Randomize

+0

1) nie ma problemu z umieszczeniem tam JLabel.setOpaque (false) i wstaw tam trochę kolorów (int, int, int, alpa), 2) JXLabel nie jest bibliotekami zewnętrznymi, jest to projekt osobisty zaakceptowany jako JLayer, 3) umieść JLabel na (taki sam jak w pierwszym punkcie) JViewPort (Mam nadzieję, że JTable jest w JScrollPane) 4) możesz sprawdzić moje posty GlassPane i JViewport oznaczone – mKorbel

+0

Próbuję z JLayer i częściowo rozwiązałem problem. Proszę spojrzeć na moje ponownie zredagowane pytanie. – Randomize

40

Wymaga to wywołanie rekurencyjne.

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

Dzięki temu rozwiązanie jest bardzo bliskie mojemu rozwiązaniu. Ale ma ten sam problem: Mam JTable i jeśli zastosujesz setEnabled (false) na nim, tabela staje się niemożliwa do kliknięcia, ale nie jest "szara" w przeciwieństwie do pozostałych składników. – Randomize

+0

Ma również problem, jeśli niektóre komponenty w kontenerze były włączone, a inne wyłączone, to wszystkie zostaną ustawione na ten sam włączony status, np .: Nie można wykonać zezwolenia, a następnie łatwo go cofnąć. – user1062589

+1

zadeklaruj enableComponents (...) static. bardzo dobra funkcja użyteczności – Exceptyon

5

użyłem następującą funkcję:

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