概要

JDK 7で導入されたJLayerを利用して指定したコンポーネントへの入力を禁止します。

サンプルコード

class DisableInputLayerUI extends LayerUI<JPanel> {
  private static final String CMD_REPAINT = "repaint";
  private boolean isRunning;

  @Override public void paint(Graphics g, JComponent c) {
    super.paint(g, c);
    if (!isRunning) {
      return;
    }
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f));
    g2.setPaint(Color.GRAY);
    g2.fillRect(0, 0, c.getWidth(), c.getHeight());
    g2.dispose();
  }

  @Override public void installUI(JComponent c) {
    super.installUI(c);
    if (c instanceof JLayer) {
      JLayer jlayer = (JLayer) c;
      jlayer.getGlassPane().setCursor(
          Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
      jlayer.setLayerEventMask(
          AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK
          | AWTEvent.MOUSE_WHEEL_EVENT_MASK | AWTEvent.KEY_EVENT_MASK
          | AWTEvent.FOCUS_EVENT_MASK | AWTEvent.COMPONENT_EVENT_MASK);
    }
  }

  @Override public void uninstallUI(JComponent c) {
    if (c instanceof JLayer) {
      ((JLayer) c).setLayerEventMask(0);
    }
    super.uninstallUI(c);
  }

  @Override public void eventDispatched(AWTEvent e, JLayer<? extends JPanel> l) {
    if (isRunning && e instanceof InputEvent) {
      ((InputEvent) e).consume();
    }
  }

  public void start() {
    if (isRunning) {
      return;
    }
    isRunning = true;
    firePropertyChange(CMD_REPAINT, false, true);
  }

  public void stop() {
    isRunning = false;
    firePropertyChange(CMD_REPAINT, true, false);
  }

  @Override public void applyPropertyChange(PropertyChangeEvent pce, JLayer<? extends JPanel> l) {
    String cmd = pce.getPropertyName();
    if (CMD_REPAINT.equals(cmd)) {
      l.getGlassPane().setVisible((Boolean) pce.getNewValue());
      l.repaint();
    }
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、JLayerを設定した任意のコンポーネントへの入力可・不可を切り替えることができます。

  • 入力禁止中に半透明グレー表示
    • LayerUI<JPanel>#paint(...)をオーバーライドして表示を変更
  • マウス、キー入力の禁止
    • LayerUI<JPanel>#eventDispatched(...)をオーバーライドして((InputEvent) e).consume()を使用しイベントを消費
  • マウスカーソルを砂時計に変更
    • Cursor.WAIT_CURSORを設定したGlassPaneの表示を切り替える

参考リンク

コメント