📄 sortinganimationpainter.java
字号:
package sortingAnimation;
import java.awt.*;
import javax.swing.*;
import animationController.AnimationController;
import animationController.SortingAnimationController;
import graphicAnimation.*;
/**
* 排序算法演示绘制器,负责创建演示的主界面,创建演示区域和演示器,管理演示区域和演示器之间的关系
* 并在处理各种上下文时绘制相应的算法演示场景,这种绘制通过委托给核实的演示器来实现
*
* @author 周晓聪
* @since 2007/6/24
* @version 1.0
*/
public class SortingAnimationPainter extends AnimationPainter {
// 为说明可使用多个视图对排序算法进行展示,我们使用两个展示区域,一个是小区域 smallArea,用盒子或圆形的整数构成的数组进行展示
// 一个是主区域 mainArea,用矩形条构成的数组或用树表示的数组(堆排序时)进行展示
protected AnimationArea smallArea = null; // 小区域的显示空间
protected AnimationArea mainArea = null; // 主区域的显示空间
protected AnimationArea infoArea = null; // 信息提示区,包括各种颜色代表的意思,并动态显示移动、交换、比较的次数
protected SortingArrayAnimator boxAnimator = null;
protected SortingArrayAnimator smallAreaAnimator = null; // 小区域使用的演示器
protected SortingArrayAnimator mainAreaAnimator = null; // 主区域使用的演示器
protected SortingInfoAnimator infoAnimator = null; // 信息提示区域使用的演示器
protected SortingAnimationController localController = null;
public SortingAnimationPainter(JComponent parent, JComponent[] toBlock, AnimationController controller) {
super(parent, toBlock, controller);
localController = (SortingAnimationController)controller;
}
protected void createAnimationArea() {
// 创建各种演示区域
infoArea = new AnimationArea(localController.windowWidth, localController.infoAreaHeight);
smallArea = new AnimationArea(localController.windowWidth, localController.smallAreaHeight);
mainArea = new AnimationArea(localController.windowWidth, localController.mainAreaHeight);
parent.setLayout(new BoxLayout(parent, BoxLayout.Y_AXIS));
parent.add(infoArea);
parent.add(smallArea);
parent.add(mainArea);
}
protected void createAnimator() {
// 创建小区域所使用的演示器,通常是使用盒子视图的演示器
boxAnimator = new SortingArrayAnimator(animationDriver);
boxAnimator.setStepDelay(localController.stepDelay);
boxAnimator.setUnitMoving(localController.unitMoving);
boxAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
// 创建主区域在演示堆排序和合并排序以外的排序算法所使用的演示器,通常使用举行矩形条的演示器
mainAreaAnimator = new SortingArrayAnimator(animationDriver);
mainAreaAnimator.setStepDelay(localController.stepDelay);
mainAreaAnimator.setUnitMoving(localController.unitMoving);
mainAreaAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
// 创建提示排序时间、比较次数、移动次数、交换次数、选择次数等信息的演示器
infoAnimator = new SortingInfoAnimator();
infoAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
infoAnimator.setStartTime();
}
protected void connectAnimatorAndArea() {
// 信息演示区域的演示器是infoAnimator,其他演示区域的演示器待定,因为当排序元素很多时不使用小区域的演
// 示器,因此这里也暂时没有设置小区域的演示器为 smallAreaAnimator
infoArea.setAnimator(infoAnimator);
// 设置各演示器所分别使用的演示区域,不过同一时刻某个演示区域只有一个演示器使用,在选定要演示的排序算
// 法的同时,我们也会确定到底使用怎样的演示器
infoAnimator.setAnimationArea(infoArea);
mainAreaAnimator.setAnimationArea(mainArea);
boxAnimator.setAnimationArea(smallArea);
}
protected void useControllerParameter() {
animationDriver.setDelay(localController.animationDelay);
}
/**
* 使用数组 data 创建演示用的最初的视图
*/
public void createAnimationView(int[] data) {
// 注意在展示中可能不用 smallArea 中的展示,因此 smallAreaAnimator 可能是 null,但不允许 mainAreaAnimator 为 null
if (localController.showValue) {
smallAreaAnimator = boxAnimator;
smallArea.setAnimator(smallAreaAnimator);
boxAnimator.createBoxAnimationScene(data, new Point(localController.startX, localController.smallStartY), localController.elementWidth, 0, Color.white);
} else {
smallAreaAnimator = null;
smallArea.setAnimator(null);
}
// 这时总有 mainAreaAnimator == rectAnimaotr || mainAreaAnimator == mergeAnimator
mainArea.setAnimator(mainAreaAnimator);
mainAreaAnimator.createRectAnimationScene(data, new Point(localController.startX, localController.mainStartY), localController.elementWidth-localController.spacingWidth, localController.spacingWidth, AnimationView.darkGreen, localController.unitHeight, localController.showValue);
Animator.sleep(localController.stepDelay);;
}
/**
* 当某一次排序终止之后,展示排序后的最终数组,并激活按钮选择下一次的演示
*/
public void showFinishedScene() {
infoAnimator.setEndTime();
if (smallAreaAnimator != null) smallAreaAnimator.showFinishedScene();
mainAreaAnimator.showFinishedScene();
// 使得原先被阻塞的构件可重新使用
for (int i = 0; i < toBlock.length; i++) toBlock[i].setEnabled(true);
}
/**
* 改变正在比较的两个数组元素的颜色值,然后驱动视图在屏幕上作相应的修改,从而展示两个正在比
* 较的数组元素
*/
public void showCompareScene(int firstIndex, int secondIndex) {
infoAnimator.incCompareCounter();
if (smallAreaAnimator != null) smallAreaAnimator.showCompareScene(firstIndex, secondIndex);
mainAreaAnimator.showCompareScene(firstIndex, secondIndex);
}
/**
* 使用动画展示正在交换的两个数组元素,注意只有在需要移动数组元素时,用树演示的堆排序和其他排序才有区别,
* 因为这时树上节点的移动没有与小区域中数组元素的移动同步(不同步可更容易看清楚节点的移动),因此没有使用
* 动画管理器 animationManager,仅仅委托给 heapAnimator 展示就可以了,而其他排序小区域与主区域的数组元
* 素移动是同步的,因此需要 animationManager 在下面的方法一起 run ,而不是委托给 mainAreaAnimator 进行
* 动画展示
*/
public void showSwapScene(int firstIndex, int secondIndex) {
infoAnimator.incSwapCounter();
animationDriver.clear();
if (smallAreaAnimator != null) smallAreaAnimator.createSwapAnimation(firstIndex, secondIndex);
mainAreaAnimator.createSwapAnimation(firstIndex, secondIndex);
animationDriver.run();
if (smallAreaAnimator != null) smallAreaAnimator.swapElementView(firstIndex, secondIndex);
mainAreaAnimator.swapElementView(firstIndex, secondIndex);
Animator.sleep(localController.stepDelay);;
}
/**
* 使用动画展示数组 fromIndex 处的元素向 toIndex 处的移动。注意,为了使连续移动显得快一些,移动元素没有步延迟
*/
public void showMoveElementScene(int fromIndex, int toIndex) {
infoAnimator.incMoveCounter();
animationDriver.clear();
if (smallAreaAnimator != null) smallAreaAnimator.createMoveElementAnimation(fromIndex, toIndex);
mainAreaAnimator.createMoveElementAnimation(fromIndex, toIndex);
animationDriver.run();
}
/**
* 使用动画展示被选中元素与 index 处元素的交换。注意,堆排序应该不会展示这种情况!
*/
public void showSwapSelectedScene(int index) {
infoAnimator.incSwapCounter();
animationDriver.clear();
if (smallAreaAnimator != null) smallAreaAnimator.createSwapSelectedAnimation(index);
mainAreaAnimator.createSwapSelectedAnimation(index);
animationDriver.run();
if (smallAreaAnimator != null) smallAreaAnimator.swapElementView(index);
mainAreaAnimator.swapElementView(index);
Animator.sleep(localController.stepDelay);;
}
/**
* 使用动画展示被选中元素与 index 处元素的比较
*/
public void showCompareSelectedScene(int index) {
infoAnimator.incCompareCounter();
if (smallAreaAnimator != null) smallAreaAnimator.showCompareSelectedScene(index);
mainAreaAnimator.showCompareSelectedScene(index);
}
/**
* 设置正被选中的元素的颜色值,然后驱动视图在屏幕上作相应的修改,从而使用特别的颜色展示正被选中的元素
* @param index 待选中的元素
*/
public void showSelectScene(int index) {
infoAnimator.incSelectCounter();
if (smallAreaAnimator != null) smallAreaAnimator.showSelectScene(index);
mainAreaAnimator.showSelectScene(index);
Animator.sleep(localController.stepDelay);;
}
/**
* 使用动画展示放置被选中元素到 index 处,也就是将被选中的元素移动到 index 处
*/
public void showPlaceScene(int index) {
infoAnimator.incMoveCounter();
animationDriver.clear();
if (smallAreaAnimator != null) smallAreaAnimator.createPlaceAnimation(index);
mainAreaAnimator.createPlaceAnimation(index);
animationDriver.run();
if (smallAreaAnimator != null) smallAreaAnimator.showNormalColor(index);
mainAreaAnimator.showNormalColor(index);
Animator.sleep(localController.stepDelay);;
}
/**
* 展示快速排序或合并排序时正在排序或合并的数组范围
*/
public void showSortingScope(int startIndex, int endIndex) {
if (smallAreaAnimator != null) smallAreaAnimator.showSortingScope(startIndex, endIndex);
if (!localController.useDotViewInMainArea) mainAreaAnimator.showSortingScope(startIndex, endIndex);
}
/**
* 展示快速排序时用于划分时的元素,该元素是 index 处的元素
*/
public void showBaseLine(int index) {
if (smallAreaAnimator != null) smallAreaAnimator.showBaseLine(index);
if (!localController.useDotViewInMainArea) mainAreaAnimator.showBaseLine(index);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -