概要

JOptionPaneを追加したJWindowを、スライドインアニメーションを使ってデスクトップ上に表示します。

サンプルコード

class SlideInNotification implements PropertyChangeListener, HierarchyListener {
  private static final int DELAY = 5;
  private final JFrame frame;
  private JWindow dialog;
  private Timer animator;
  private int dx;
  private int dy;

  public SlideInNotification(JFrame frame) {
    super();
    this.frame = frame;
  }

  public void startSlideIn(final SlideInAnimation slideInAnimation) {
    if (animator != null && animator.isRunning()) {
      return;
    }
    if (dialog != null && dialog.isVisible()) {
      dialog.dispose();
    }
    GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
    Rectangle desktopBounds = env.getMaximumWindowBounds();

    JOptionPane optionPane = new JOptionPane(
        "Warning", JOptionPane.WARNING_MESSAGE);
    DragWindowListener dwl = new DragWindowListener();
    optionPane.addMouseListener(dwl);
    optionPane.addMouseMotionListener(dwl);
    optionPane.addPropertyChangeListener(this);
    optionPane.addHierarchyListener(this);

    GraphicsConfiguration gc = frame.getGraphicsConfiguration();
    dialog = new JWindow(gc);
    dialog.getContentPane().add(optionPane);
    dialog.pack();

    final Dimension d = dialog.getContentPane().getPreferredSize();
    dx = desktopBounds.width - d.width;
    dy = desktopBounds.height;

    dialog.setLocation(new Point(dx, dy));
    dialog.setVisible(true);

    animator = new Timer(DELAY, new ActionListener() {
      private int count;
      @Override public void actionPerformed(ActionEvent e) {
        double a = 1d;
        switch (slideInAnimation) {
          case EASE_IN:
          a = AnimationUtil.easeIn(count++ / (double) d.height);
          break;
          case EASE_OUT:
          a = AnimationUtil.easeOut(count++ / (double) d.height);
          break;
          case EASE_IN_OUT:
          default:
          a = AnimationUtil.easeInOut(count++ / (double) d.height);
          break;
        }
        int visibleHeight = (int) (.5 + a * d.height);
        if (visibleHeight >= d.height) {
          visibleHeight = d.height;
          animator.stop();
        }
        dialog.setLocation(new Point(dx, dy - visibleHeight));
      }
    });
    animator.start();
  }

  @Override public void propertyChange(PropertyChangeEvent e) {
    if (dialog != null && dialog.isVisible() && e.getNewValue() != null &&
        e.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
      dialog.dispose();
    }
  }

  @Override public void hierarchyChanged(HierarchyEvent e) {
    JComponent c = (JComponent) e.getComponent();
    if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0 &&
        animator != null && !c.isDisplayable()) {
      animator.stop();
    }
  }
}
View in GitHub: Java, Kotlin

解説

上記のサンプルでは、Window#setLocation(int, int)メソッドを使用してJOptionPaneを追加したJWindowのデスクトップ上での表示位置を変更し、画面右下からスライドインするように設定しています。

  • マルチスクリーン環境ではメインのJFrameが存在する画面(frame.getGraphicsConfiguration())に警告(new JWindow(GraphicsConfiguration))がスライドインすることを想定しているが未検証
  • JOptionPane.WARNING_MESSAGE以外のJOptionPaneは未検証
  • このページのスクリーンショットでは親フレーム中央にJOptionPaneが表示されているが、これは手動で移動している

参考リンク

コメント