【问题标题】:How to disable all components in a JPanel如何禁用 JPanel 中的所有组件
【发布时间】:2013-10-19 22:24:50
【问题描述】:

在我的 JPanel 中,我有许多组件,包括其他 JPanel、JLabels、JTextAreas 和 JButton。因为我想实现一个教程模式,其中出现另一个窗口并且我的主 JPanel 中的所有内容都被禁用,因为新窗口一个一个地解释了每个“功能”......我想知道如何禁用我里面的所有组件原始JPanel。我知道你可以使用:

component.setEnabled(false);

但我不想为我的 JPanel 中的每个组件编写它。我想知道是否可以使用 for 循环或其他方式禁用我的 JPanel 中的所有组件?

注意:嵌套的 JPanel 中也有组件,就像顺序一样

主 JPanel ---> 嵌套 JPanel ---> 组件

我还希望最终组件也被禁用...

谢谢!感谢所有帮助!

【问题讨论】:

  • 你能在整个JPanel上setEnabled(false);吗?我不确定这是否有效。
  • 不,我已经试过了。我相信 JPanel 上的 setEnalbled(false) 只会禁用 JPanel 本身的输入,例如面板上的鼠标点击而不是组件本身
  • 试试看一下JXLayer/Jlayer

标签: java swing jpanel components


【解决方案1】:

我使用了以下函数:

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

    Component[] components = panel.getComponents();

    for (Component component : components) {
        if (component instanceof JPanel) {
            setPanelEnabled((JPanel) component, isEnabled);
        }
        component.setEnabled(isEnabled);
    }
}

【讨论】:

  • 应该使用equals(..)比较字符串值而不是==
  • 当 JLists 在 JPanel 内时,这将不起作用:S
【解决方案2】:

查看Disabled Panel 了解一些解决方案。

一个使用禁用的 GlassPane 类型的方法,另一个递归地禁用组件,同时跟踪组件的当前状态,以便以后可以正确启用。

【讨论】:

  • 这是否会跟踪状态更改之间对组件所做的更改?即,我禁用“父”,启用和禁用一些子,然后启用“父”,是否会保持新状态?
  • @MadProgrammer,不,它假定禁用面板时不会发生状态更改(即所有组件保持禁用状态)。因此,它只会在面板被禁用时跟踪启用的组件。启用面板时,只会启用这些组件。
【解决方案3】:

JPanel 是一个容器。容器有一个 getComponents() 方法。您应该递归地遍历组件树。
如果当前子节点也是一个容器(instanceof),你可以再次递归调用,否则你只需调用 setEnabled(false)。

【讨论】:

  • 这种方法的危险在于它忽略了子组件的启用状态。您还需要遍历所有子容器
  • 这不适用于面板内的 JLists。
【解决方案4】:

简单快捷的方法:)

for (Component cp : yourPanle.getComponents() ){
        cp.setEnabled(false);
 }

【讨论】:

    【解决方案5】:

    我不久前使用JXLayer 实现了一个解决方案,它使用它的锁定效果功能在容器上提供一个“阻塞”层。

    它基于JXLayer 3.x 并使用来自JHLabs 的过滤器来生成它的“灰度”效果

    import com.jhlabs.image.GrayscaleFilter;
    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.LayoutManager;
    import java.awt.RenderingHints;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import javax.swing.JComponent;
    import javax.swing.JPanel;
    import org.jdesktop.jxlayer.JXLayer;
    import org.jdesktop.jxlayer.QualityHints;
    import org.jdesktop.jxlayer.plaf.BetterBufferedImageOpEffect;
    import org.jdesktop.jxlayer.plaf.LayerUI;
    import org.jdesktop.jxlayer.plaf.ext.LockableUI;
    
    public class CoreXPane extends JPanel {
    
        private JXLayer<JPanel> layer;
        private FadedLockUI fadedLockUI;
        private JPanel pnlBody;
    
        public CoreXPane(LayoutManager layout) {
    
            super.setLayout(new BorderLayout());
            super.addImpl(getLayer(), BorderLayout.CENTER, 0);
    
            setLayout(layout);
    
        }
    
        public CoreXPane() {
    
            this(new BorderLayout());
    
        }
    
        @Override
        public void setEnabled(boolean enabled) {
    
            getLockUI().setLocked(!enabled);
            getBodyPane().setEnabled(enabled);
            super.setEnabled(enabled);
    
        }
    
        @Override
        protected void addImpl(Component comp, Object constraints, int index) {
    
            getBodyPane().add(comp, constraints, index);
    
        }
    
        @Override
        public void remove(int index) {
    
            getBodyPane().remove(index);
    
        }
    
        @Override
        public void removeAll() {
    
            getBodyPane().removeAll();
    
        }
    
        protected FadedLockUI getLockUI() {
    
            if (fadedLockUI == null) {
    
                fadedLockUI = new FadedLockUI();
    
            }
    
            return fadedLockUI;
    
        }
    
        @Override
        public void invalidate() {
    
            getLockUI().invalidate();
    
            super.invalidate();
    
        }
    
        @Override
        public void revalidate() {
    
            getLockUI().revalidate();
            super.revalidate();
    
        }
    
        @Override
        public void repaint() {
    
            getLockUI().repaint();
    
            super.repaint();
    
        }
    
        protected void getLayers(List<LayerUI> layers) {
    
            layers.add(getLockUI());
    
        }
    
        protected JXLayer<JPanel> getLayer() {
    
            if (layer == null) {
    
                List<LayerUI> layers = new ArrayList<LayerUI>(4);
                getLayers(layers);
    
                JComponent wrapper = getBodyPane();
                for (LayerUI ui : layers) {
    
                    wrapper = new JXLayer(wrapper, ui);
    
                }
    
                layer = (JXLayer<JPanel>) wrapper;
    
            }
    
            return layer;
    
        }
    
        @Override
        public void setLayout(LayoutManager mgr) {
    
            getBodyPane().setLayout(mgr);
    
        }
    
        @Override
        public LayoutManager getLayout() {
    
            return getBodyPane().getLayout();
    
        }
    
        public JPanel getBodyPane() {
    
            if (pnlBody == null) {
    
                pnlBody = new JPanel();
                pnlBody.setLayout(new BorderLayout());
    
            }
    
            return pnlBody;
    
        }
    
        @Override
        public void setOpaque(boolean isOpaque) {
    
            super.setOpaque(isOpaque);
            getBodyPane().setOpaque(isOpaque);
    
        }
    
        public static class FadedLockUI extends LockableUI {
    
            public static Map<RenderingHints.Key, Object> mapRenderHints = new QualityHints();
    
            public FadedLockUI() {
    
                setLockedEffects(new BufferedImageOpEffect(new GrayscaleFilter()));
    
                mapRenderHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); // okay
                mapRenderHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // bad
                mapRenderHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); // okay
                mapRenderHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                mapRenderHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                mapRenderHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                mapRenderHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    
            }
    
            @Override
            protected Map<RenderingHints.Key, Object> getRenderingHints(JXLayer<? extends JComponent> l) {
                return mapRenderHints;
            }
    
            public void repaint() {
                setDirty(true);
            }
    
            public void invalidate() {
                setDirty(true);
            }
    
            public void revalidate() {
                setDirty(true);
            }
        }
    }
    

    查看LockableUI了解更多详情

    【讨论】:

      【解决方案6】:

      我刚刚创建了一个小类,它递归地禁用给定容器中的所有内容,然后重新启用之前禁用的每个组件(以相反的顺序)。它还允许从禁用中排除任意组件,这是我添加的一个功能,因为 JLabels 在禁用时看起来不必要地难看。

      像魅力一样工作。由于这个问题经常出现,而且我今天早些时候碰巧看到了这篇文章,所以这是课程:

      import java.awt.*;
      import java.util.ArrayList;
      import java.util.List;
      
      /**
       * Purpose: To recursively disable (and later re-enable) all components of a container, e.g. if you want to clearly show
       * that a program is busy or if you want to prevent clicks and other inputs that piled up meanwhile to affect a window
       * once the program becomes responsive again. Though the solution for that would be simpler: Just disable the window and
       * then, in a SwingUtilities.invokeLater(), re-enable it. This makes sure that before this happens, all input events are
       * eaten.
       */
      final public class EverythingDisablerAndReenabler { // v[1, 2016-12-05 14!30 UTC] by dreamspace-president.com
      
          final private Container rootContainerForWhatShouldBeDisabled;
          final private Class<?>[] componentClassesToBeIgnored;
          final private List<Component> componentsToReenable = new ArrayList<>();
      
          private boolean disableHasBeenCalled = false; // Order is strictly upheld via IllegalStateException!
      
          /**
           * @param rootContainerForWhatShouldBeDisabled NOT NULL! The Container whose components are to be recursively
           *                                             disabled. The container itself will not be disabled.
           * @param componentClassesToBeIgnored          null or an array of classes (e.g. containing JLabel.class) that
           *                                             should be excluded from disabling. Adding a Container here does not
           *                                             affect the recursive process.
           * @throws IllegalArgumentException if the container argument is null. In case someone wonders why I don't use
           *                                  {@link NullPointerException} here: Null can be a perfectly legal argument in
           *                                  other places, but here, it is not. If an argument does not check out, the choice
           *                                  of Exception, of course, is IllegalArgument, not NullPointer.
           */
          public EverythingDisablerAndReenabler(final Container rootContainerForWhatShouldBeDisabled, final Class<?>[] componentClassesToBeIgnored) {
      
              if (rootContainerForWhatShouldBeDisabled == null) {
                  throw new IllegalArgumentException();
              }
              this.rootContainerForWhatShouldBeDisabled = rootContainerForWhatShouldBeDisabled;
              this.componentClassesToBeIgnored = componentClassesToBeIgnored;
          }
      
          /**
           * Disables everything recursively, except the excluded types.
           *
           * @throws IllegalStateException if called twice in a row.
           */
          public void disable() {
      
              if (disableHasBeenCalled) {
                  throw new IllegalStateException();
              }
              disableHasBeenCalled = true;
              componentsToReenable.clear();
              disableEverythingInsideThisHierarchically(rootContainerForWhatShouldBeDisabled);
          }
      
          /**
           * @throws IllegalStateException if called twice in a row or if disable() had not been called yet.
           */
          public void reenable() {
      
              if (!disableHasBeenCalled) {
                  throw new IllegalStateException();
              }
              disableHasBeenCalled = false;
      
              for (int i = componentsToReenable.size() - 1; i >= 0; i--) {
                  componentsToReenable.get(i).setEnabled(true);
              }
              componentsToReenable.clear();
          }
      
          private void disableEverythingInsideThisHierarchically(final Container container) {
      
              final Component[] components = container.getComponents();
              for (Component component : components) {
      
                  if (component != null) {
      
                      // RECURSION FIRST
                      if (component instanceof Container) {
                          disableEverythingInsideThisHierarchically((Container) component);
                      }
      
                      // AND THEN DEAL WITH THE ELEMENTS
                      if (component.isEnabled()) {
                          boolean found = false;
                          if (componentClassesToBeIgnored != null) {
                              for (Class<?> cls : componentClassesToBeIgnored) {
                                  if (component.getClass() == cls) {
                                      found = true;
                                      break;
                                  }
                              }
                          }
                          if (!found) {
                              component.setEnabled(false);
                              componentsToReenable.add(component);
                          }
                      }
                  }
              }
          }
      
      
      }
      

      【讨论】:

      • 我意识到“List”不是最佳选择:它应该是“List>”,对可重新启用的代码进行一些微小的调整。这将确保不会保留不必要的实例。
      【解决方案7】:
      private void disableComponents(Container panel) {
      
          for (Component c : panel.getComponents()) {
              if (c instanceof Container)
                  disableComponents((Container) c);
      
              c.setEnabled(false);
      
              if (c instanceof JTextField || c instanceof JTextArea)
                  ((JTextComponent) c).setText("");
              if (c instanceof JXDatePicker)
                  ((JXDatePicker) c).setDate(null);
              if (c instanceof JComboBox)
                  ((JComboBox) c).setSelectedIndex(-1);
              if (c instanceof JCheckBox)
                  ((JCheckBox) c).setSelected(false);
          }
      }
      
       private void enableComponents(Container panel) {
      
          for (Component c : panel.getComponents()) {
              if (c instanceof Container)
                  enableComponents((Container) c);
              c.setEnabled(true);
          }
      }
      

      您可以在 JPanel 中像 disableComponents(this); 一样拨打电话。

      【讨论】:

        猜你喜欢
        • 2016-11-15
        • 2015-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        相关资源
        最近更新 更多