2012-10-03 53 views
2

美好的一天。擺動JDialog的內容窗格在執行幻燈片時不會更新

我想要實現的一個對話框(帶有鍵盤,但這不在該問題的範圍之內)出現在框架上,當按下按鈕時從底部滑入。

我是一名初學者,請不要責怪問題是否明顯。
我拋出了一些代碼,達到(有一些缺陷),但開始和結束位置之間的對話的實際位置不顯示給用戶。該對話框在動畫完成時顯示,不顯示。 任何人都知道他們爲什麼不顯示?

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; 
} 
} 

回答

2

T他的問題在於你的方法in()out()在EDT上運行,並且阻止它直到它們結束,這會阻止Repaint事件發送並顯示鍵盤的修改位置。

使用一個Swing計時器來代替您的動畫。這將允許中間重繪實際發生。

+0

謝謝,這有助於! – user1712376