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 回答