我有带有淡入淡出动画的 JTabbedPane,当用户单击选项卡时执行该动画。为了处理动画我重写stateChanged
method.
public class AnimatedJTabbedPane extends JTabbedPane implements ChangeListener, TimingTarget{
/**
*
*/
private static final long serialVersionUID = 1L;
protected BufferedImage previousTabImage;
protected BufferedImage bufferImage;
protected BufferedImage nextTabImage;
protected boolean animationStarted = false;
protected boolean paintPreviousImage = false;
protected boolean leftToRightIndex = false;
protected float fraction = 0.0f;
protected Animator animator;
protected int previousTabIndex = -1;
public AnimatedJTabbedPane(int tabPlacement) {
super(tabPlacement);
this.animator = new Animator(300, this);
this.animator.setAcceleration(0.1f);
this.animator.setDeceleration(0.8f);
this.addChangeListener(this);
}
public void stateChanged(ChangeEvent e) {
if(this.previousTabIndex != this.getSelectedIndex()){
if(this.previousTabIndex == -1){
this.previousTabIndex = this.getSelectedIndex();
}
else{
this.paintPreviousImage = true;
boolean interrupted = false;
if(this.animator.isRunning()){
this.animator.stop();
interrupted= true;
}
Component previousComponent = this.getComponentAt(this.previousTabIndex);
this.previousTabImage = this.getGraphicsConfiguration().createCompatibleImage(
previousComponent.getWidth(), previousComponent.getHeight(), Transparency.TRANSLUCENT);
previousComponent.paint(this.previousTabImage.getGraphics());
Component nextComponent = this.getComponentAt(this.getSelectedIndex());
this.nextTabImage = this.getGraphicsConfiguration().createCompatibleImage(
previousComponent.getWidth(), previousComponent.getHeight(), Transparency.TRANSLUCENT);
nextComponent.paint(this.nextTabImage.getGraphics());
if(this.previousTabIndex < this.getSelectedIndex()){
this.leftToRightIndex = true;
}
else{
this.leftToRightIndex = false;
}
this.previousTabIndex = this.getSelectedIndex();
if(interrupted){
this.animator.setStartFraction(1-this.fraction);
}
else{
this.animator.setStartFraction(0);
}
this.animationStarted = true;
this.animator.start();
}
}
}
@Override
public void paintChildren(Graphics g){
if(this.getComponentCount() != 0){
Rectangle childrenPosition = this.getComponentAt(0).getBounds();
if(this.bufferImage == null ||
this.bufferImage.getWidth() != this.getWidth() ||
this.bufferImage.getHeight() != this.getHeight()){
this.bufferImage = new BufferedImage(
this.getWidth(),
this.getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
if(this.animationStarted){
if(this.paintPreviousImage){
g.drawImage(this.bufferImage, 0, 0, null);
this.paintPreviousImage = false;
}
else{
Graphics2D g2d = (Graphics2D)this.bufferImage.createGraphics();
int x = (int)childrenPosition.getX();
int y = (int)childrenPosition.getY();
this.performFadeAnimation(g2d, x, y);
g.drawImage(this.bufferImage, 0, 0, null);
g2d.dispose();
}
g.dispose();
}
else{
Graphics2D g2d = (Graphics2D)this.bufferImage.createGraphics();
super.paintChildren(g2d);
g.drawImage(this.bufferImage, 0, 0, null);
g2d.dispose();
g.dispose();
}
}
else{
super.paintChildren(g);
}
}
protected void performFadeAnimation(Graphics2D g2d, final double x, final double y){
g2d.drawImage(this.previousTabImage, (int)x, (int)y, null);
AlphaComposite composite =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, this.fraction);
g2d.setComposite(composite);
g2d.drawImage(this.nextTabImage, (int)x, (int)y, null);
}
@Override
public void begin() {
// TODO Auto-generated method stub
}
@Override
public void end() {
this.animationStarted = false;
this.repaint();
this.nextTabImage.flush();
this.nextTabImage = null;
this.previousTabImage.flush();
this.previousTabImage = null;
}
@Override
public void repeat() {
// TODO Auto-generated method stub
}
@Override
public void timingEvent(float fraction) {
this.fraction = fraction;
this.repaint();
}
}
当用户手动单击选项卡时,这非常有用。stateChanged
事件被调用并且选项卡随着动画而变化。
我需要从代码中更改选定的选项卡,所以我使用setSelectedIndex(int)
method.
public void setSelectedTab(int tab){
animatedTabbedPane.setSelectedIndex(tab);
}
但现在选项卡在之后立即更改setSelectedIndex
结束 - 没有动画,然后stateChanged
方法被调用,因此选项卡切换回之前选择的选项卡并执行(正确)我的动画。
所以选项卡会改变两次,第一次没有动画,然后setSelectedIndex
以及之后的第二次stateChanged
in AnimatedJTabbedPane
.
我需要类似的东西:
animatedTabbedPane.firePropertyChange("stateChanged", old, new);
我只想更改选项卡stateChanged
方法,所以我可以不用默认setSelectedIndex
方法。我怎样才能做到这一点?
EDIT我的问题的小图表:
红线代表可见性。因此,当用户仅更改选项卡时stateChanged
叫做,tab 0顺利地改变为tab 1。当我使用setSelectedIndex
tab 0立即替换为tab 1只有这样我才能看到我想要的动画stateChanged
,因此用户会看到闪光。