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