2

全てにおいて良い日。

私が達成しようとしているのは、ボタンが押されたときに下からスライドしてダイアログ(キーボードを使用しますが、これはこの質問の範囲外です)をフレームに表示することです。

私はスイングの初心者です。問題が明らかな場合は責任を負わないでください。
私はそれを達成するいくつかのコードを投げました(いくつかの欠陥があります)が、開始位置と終了位置の間のダイアログの実際の位置はユーザーに表示されません。アニメーションが完了すると、ダイアログは表示されずに表示されます。なぜ彼らが見せられないのか誰もが知っていますか?

public class TestSliding
extends JFrame {

private static Window kbdOwner;
private static final double kbdHeightRatio = 1d / 4d;
private static final long kbdSlideDurationMs = 3000;

public static Point getKbdLocation() {
  int x = (int) kbdOwner.getBounds().getLocation().getX();
  int y =
    (int) (kbdOwner.getBounds().getLocation().getY() + kbdOwner.getBounds().getSize().getHeight() - getKbdSize()
        .getHeight());

  return new Point(x, y);
}

public static Dimension getKbdSize() {
  int width = (int) kbdOwner.getBounds().getSize().getWidth();
  int height = (int) (width * kbdHeightRatio);

  return new Dimension(width, height);
}

public static void main(String[] args) {
  SwingUtilities.invokeLater(new Runnable() {

    @Override
    public void run() {
      new TestSliding().setVisible(true);
    }
  });
}

private JButton toogleBtn = new JButton("Toogle");
private VirtualKeyboardSlide slide;

public TestSliding() {
  super();
  kbdOwner = this;
  setTitle("Test Sliding");
  setDefaultCloseOperation(EXIT_ON_CLOSE);
  setLayout(new BorderLayout());
  setBackground(Color.BLUE);

  setResizable(false);
  setSize(1024, 768);

  toogleBtn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent argE) {
      switch (getSlide().getState()) {
        case OUT: {
          getSlide().in();
          break;
        }

        case IN: {
          getSlide().out();
          break;
        }
      }
    }
  });

  JPanel panel = new JPanel();
  getContentPane().add(panel);
  panel.add(toogleBtn);
}

public VirtualKeyboardSlide getSlide() {
  if (slide == null) {
    slide = new VirtualKeyboardSlide();
    slide.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    slide.pack();
    slide.setSize(getKbdSize());
    slide.setLocation(getKbdLocation());
    slide.setVisible(true);
  }

  return slide;
}

public interface IVirtualKeyboardPane {
  public void in();
  public void out();
}

public class VirtualKeyboardSlide
....
// see below
....

public class VirtualKeyboardPane
....
// see below
....

}

ダイアログ:

private class VirtualKeyboardSlide
  extends JDialog {

private static final long serialVersionUID = 1L;

private KeyboardState kbdState_ = OUT;

private double height;
private double width;

/**
 * Constructs a <code>VirtualKeyboardDialog</code>.
 */
public VirtualKeyboardSlide() {
  this(new VirtualKeyboardPane());
}

public <T extends Container & IVirtualKeyboardPane> VirtualKeyboardSlide(T contentPane) {
  super(kbdOwner, ModalityType.MODELESS);
  setContentPane(contentPane);
  setUndecorated(true);
  setState(OUT);
  setBackground(new Color(0, 0, 0, 0));
}

/**
 * Returns the state of the keyboard
 * @return the state of the keyboard
 */
public synchronized KeyboardState getState() {
  return kbdState_;
}

public void in() {
  if (canSlideIn()) {
    setState(SLIDING_IN);

    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        getVirtualKeyboardPane().in();
        setState(IN);
      }
    });
  }
}

public void out() {
  if (canSlideOut()) {
    setState(SLIDING_OUT);

    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        getVirtualKeyboardPane().out();
        setState(OUT);
      }
    });
  }
}

/**
 * Sets the keyboard state
 * @param argState
 */
public synchronized void setState(KeyboardState argState) {
  kbdState_ = argState;
}

/**
 * Returns true if the keyboard can slide in now
 * @return true if the keyboard can slide in now
 */
protected boolean canSlideIn() {
  if (!getState().equals(OUT)) {
    return false;
  }

  return true;
}

/**
 * Returns true if the keyboard can slide out now
 * @return true if the keyboard can slide out now
 */
protected boolean canSlideOut() {
  if (!getState().equals(IN)) {
    return false;
  }

  return true;
}

protected IVirtualKeyboardPane getVirtualKeyboardPane() {
  return (IVirtualKeyboardPane) getContentPane();
}

}

KeyboardStateは、キーボードの状態を定義する列挙型です。

public enum KeyboardState {
  SLIDING_IN, SLIDING_OUT, IN, OUT, DIED
}

ダイアログのコンテンツペインは、次のクラスで表されます。

public class VirtualKeyboardPane
  extends JPanel
  implements IVirtualKeyboardPane {

private static final long serialVersionUID = 1L;

private int height_;
private int width_;

private int normalHeight_;
private int normalWidth_;

private int x_;
private int y_;

public VirtualKeyboardPane() {
  super();
  setFocusable(false);
  setOpaque(false);
  setBorder(BorderFactory.createEmptyBorder());
}

/** {@inheritDoc} */
@Override
public void in() {
  normalHeight_ = (int) getKbdSize().getHeight();
  normalWidth_ = (int) getKbdSize().getWidth();
  width_ = normalWidth_;
  x_ = 0;
  y_ = 0;

  long currentTime = System.currentTimeMillis();
  long startTime = currentTime;
  long endTime = currentTime + kbdSlideDurationMs;

  height_ = 0;
  while (currentTime < endTime) {
    long elapsedTime = currentTime - startTime;
    float f = ((float) elapsedTime / (float) kbdSlideDurationMs);

    height_ = (int) (f * normalHeight_);

    y_ = normalHeight_ - height_;

    repaint();
    currentTime = System.currentTimeMillis();
  }
}

/** {@inheritDoc} */
@Override
public void out() {
  normalHeight_ = (int) getKbdSize().getHeight();
  normalWidth_ = (int) getKbdSize().getWidth();
  width_ = normalWidth_;
  x_ = 0;
  y_ = normalHeight_;

  long currentTime = System.currentTimeMillis();
  long startTime = currentTime;
  long endTime = currentTime + kbdSlideDurationMs;

  height_ = normalHeight_;
  while (currentTime < endTime) {
    long elapsedTime = currentTime - startTime;
    float f = ((float) elapsedTime / (float) kbdSlideDurationMs);

    height_ = normalHeight_ - (int) (f * normalHeight_);

    y_ = normalHeight_ - height_;

    repaint();
    currentTime = System.currentTimeMillis();
  }
}

@Override
protected void paintComponent(Graphics g) {
  super.paintComponent(g);
  g.setColor(new Color(RGBToFloat(255), RGBToFloat(255), RGBToFloat(255), 0.5f));
  // g.fillRect((int) x_, (int) y_, (int) width_, (int) height_);
  g.fillRect(x_, y_, width_, height_);
}

private float RGBToFloat(int rgbValue) {
  return (rgbValue - 0.5f) / 255f;
}
}
4

1 に答える 1

2

問題は、メソッドin()out()がEDTで実行されており、終了するまでブロックされていることです。これにより、Repaintイベントがディスパッチされ、キーボードの変更された場所が表示されなくなります。

代わりにSwingタイマーを使用して、アニメーションのペースを調整してください。これにより、中間の再描画を実際に行うことができます。

于 2012-10-03T17:14:46.670 に答える