2012-06-11 183 views
6

我有一个包含JToolbar(包括几个没有文本的按钮)和JTable的JPanel,我需要启用/禁用(使内部小部件不可点击)。我试过这个:Java Swing:启用/禁用JPanel中的所有组件

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

但它不起作用。是否有更好更通用的解决方案来启用/禁用JPanel中的所有内部组件?

使用JLayer从这里的例子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(); 
    } 
    } 

} 

我仍然有2个问题:

1)在上述的事件的链接是相对只小鼠。我如何管理键盘事件?

2)如何在模糊处创建“灰色”效果?

+0

您可以设置在面板的知名度直接使用'panel.setVisible(假)' –

+0

调用setVisible(假)使得组件“看不见“,但实际上我需要它仍然可见但灰色。 – Randomize

+0

这个线程有帮助吗? http://stackoverflow.com/a/305551/1417974 –

回答

2

您可以通过默认MouseEvents覆盖整个Container/JComponent

  1. GlassPane块,但没有键盘,需要消耗从工具包

  2. JLayer基于JXLayer(的Java6)(Java7)

  3. 所有KeyEvent
  4. 看不到原因(s)为什么不适合你

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

感谢您的多重答案:1)GlassPane很有趣,我不知道如何获得模糊或变灰的效果。 2)我正在使用Java 6,我不想(现在)使用外部库。 3)该解决方案存在JTable的问题。 – Randomize

+0

1)没有问题放在那里JLabel。setOpaque(false)并放置一些Color(int,int,int,alpa),2)JXLabel不是外部库,这是将个人项目接受为JLayer,3)将JLabel放入(与第一个点相同)JViewPort (我希望JTable进入JScrollPane)4)哟可以检查我的帖子GlassPane和JViewport的标记 – mKorbel

+0

我想用JLayer和我解决了部分问题。请看看我重新编辑的问题。 – Randomize

40

它需要一个递归调用。

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

感谢这个解决方案非常接近我的解决方案。但它有同样的问题:我有一个JTable,如果你对它应用setEnabled(false),表格变得不可点击,但它不会与其他组件相反。 – Randomize

+0

它也有一个问题,如果容器中的某些组件被启用和禁用,则它们将全部被设置为相同的启用状态,例如:您不能启用,然后简单地撤消它。 – user1062589

+1

declare enableComponents(...)static。非常好的实用功能 – Exceptyon

5

我用下面的功能:

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