PopupFactory,从而使得swing的所有弹出窗口都具有这种效果。
/**
* 这个类是一个Popup代理,将真实Popup的显示过程动画弹出
*/
class PopupProxy extends Popup implements ActionListener{
//一些常量
private static final int ANIMATION_FRAME_INTERVAL=10;
private static final int ANIMATION_FRAMES=10;
//被代理的弹出式窗口,这个弹出式窗口是从缺省工厂那儿获得的。
private Popup popupProxy;
//当前组件
private Component topComponent;
//弹出式窗口最终尺寸
private Dimension fullSize;
//动画时钟
private Timer timer;
//动画的当前帧
private int frameIndex;
public PopupProxy(Popup popup, Component component){
popupProxy=popup;
topComponent=component;
}
/**
* 覆盖show方法启动动画线程
*/
@Override
public void show() {
//代理窗口显示
popupProxy.show();
//获取显示后窗口的最终大小。
fullSize=topComponent.getSize();
//设置窗口的初始尺寸
topComponent.setSize(
horizontalExtending?0:fullSize.width,
verticalExtending?0:fullSize.height);
//初始化为第一帧
frameIndex=1;
//启动动画时钟
timer=new Timer(ANIMATION_FRAME_INTERVAL, this);
timer.start();
}
/**
* 重载hide,关闭可能的时钟
*/
@Override
public void hide() {
if(timer!=null&&timer.isRunning()){
//关闭时钟
timer.stop();
timer=null;
}
//代理弹出窗口关闭
popupProxy.hide();
}
//动画时钟事件的处理,其中一帧
public void actionPerformed(ActionEvent e) {
//设置当前帧弹出窗口组件的尺寸
topComponent.setSize(
horizontalExtending?
fullSize.width*frameIndex/ANIMATION_FRAMES:
fullSize.width,
verticalExtending?
fullSize.height*frameIndex/ANIMATION_FRAMES:
fullSize.height);
if(frameIndex==ANIMATION_FRAMES){
//最后一帧,关闭时钟
timer.stop();
timer=null;
}else
//前进一帧
frameIndex++;
}
}
public class ScrollablePopupFactory extends PopupFactory{
//是否横向滚动,缺省不
private boolean horizontalExtending;
//是否垂直滚动,缺省不
private boolean verticalExtending;
/**
* Creates a new instance of ScrollablePopupFactory
*/
public ScrollablePopupFactory(){
}
/**
* @param h 是否横向滚动
* @param v 是否垂直滚动
*/
public ScrollablePopupFactory(boolean h, boolean v) {
horizontalExtending=h;
verticalExtending=v;
}
/**
* 覆盖PopupFactory.getPopup方法提供自定义Popup代理
*
*/
@Override
public Popup getPopup(Component owner, Component contents, int x, int y) throws IllegalArgumentException {
//获取缺省的Popup
Popup popup = super.getPopup(owner, contents, x, y);
//如果纵横都不滚动,直接使用缺省的弹出式窗口
if(!(horizontalExtending||verticalExtending))
return popup;
//目前没有好办法判断弹出窗口是何种类型,只好用类名字来判断
String name=popup.getClass().getName();
if(name.equals("javax.swing.PopupFactory$HeavyWeightPopup")){
//重量级的弹出窗口,其顶层容器为JWindow
return new PopupProxy(
popup,
SwingUtilities.getWindowAncestor(contents));
}else{
//轻量级的弹出窗口
if(contents instanceof JToolTip)
//如果组件是JToolTip,则其父亲容器就是顶层容器
return new PopupProxy(
popup,
contents.getParent());
else
//其他弹出式窗口则组件本身就是顶层容器
return new PopupProxy(
popup,
contents);
}
}
/**
* 这个类是一个Popup代理,将真实Popup的显示过程动画弹出
*/
class PopupProxy extends Popup implements ActionListener{
......
}
}
public static void main(String args[]) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {}
//设置自定义的PopupFactory,注意纵横都扩展,可以改变布尔值只横向或纵向扩展,或者没有动画
PopupFactory.setSharedInstance(new ScrollablePopupFactory(true, true));
EventQueue.invokeLater(new Runnable() {
public void run() {
new ScrollablePopupDemo().setVisible(true);
}
});
}