📄 multiplesortinganimationpainter.java
字号:
package sortingAnimation;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import animationController.AnimationController;
import animationController.SortingAnimationController;
import graphicAnimation.*;
/**
* 排序算法演示绘制器,负责创建演示的主界面,创建演示区域和演示器,管理演示区域和演示器之间的关系
* 并在处理各种上下文时绘制相应的算法演示场景,这种绘制通过委托给核实的演示器来实现
*
* @author 周晓聪
* @since 2007/6/24
* @version 1.0
*/
public class MultipleSortingAnimationPainter extends AnimationPainter {
// 为说明可使用多个视图对排序算法进行展示,我们使用两个展示区域,一个是小区域 smallArea,用盒子或圆形的整数构成的数组进行展示
// 一个是主区域 mainArea,用矩形条构成的数组或用树表示的数组(堆排序时)进行展示
private AnimationArea smallArea = null; // 小区域的显示空间
private AnimationArea mainArea = null; // 主区域的显示空间
private AnimationArea infoArea = null; // 信息提示区,包括各种颜色代表的意思,并动态显示移动、交换、比较的次数
private SortingArrayAnimator smallAreaAnimator = null; // 小区域使用的演示器
private SortingArrayAnimator mainAreaAnimator = null; // 主区域使用的演示器
private HeapSortingAnimator heapAnimator = null; // 当选择堆排序并且适合用树表示的数组展示器时主区域使用的演示器
private MergeSortingAnimator mergeAnimator = null; // 当选择合并排序时使用的演示器
private SortingArrayAnimator rectAnimator = null; // 当选择合并排序和堆排序以外时主区域使用的演示器,使用矩形条进行展示
private SortingArrayAnimator boxAnimator = null; // 小区域使用的演示器,使用盒子或圆形的整数构成的数组进行展示
private SortingInfoAnimator infoAnimator = null; // 信息提示区域使用的演示器
private SortingAnimationController localController = null;
private int exitMode = 1; // 当为1时仅仅隐藏所有的演示器和GUI构件,而为-1时退出整个系统
// 有关排序的信息
private String[] buttonName = {"冒泡排序", "选择排序", "插入排序", "快速排序", "堆排序", "合并排序", "希尔排序", "退出"};
private int buttonType[] = {SortingDriver.BUBBLE_SORT, SortingDriver.SELECT_SORT, SortingDriver.INSERT_SORT, SortingDriver.QUICK_SORT, SortingDriver.HEAP_SORT, SortingDriver.MERGE_SORT, SortingDriver.SHELL_SORT, SortingDriver.EXIT_SORT};
private JButton[] sortButton = new JButton[buttonName.length];
private int currentSortorType = SortingDriver.BUBBLE_SORT;
public MultipleSortingAnimationPainter(JComponent parent, JComponent[] toBlock, AnimationController controller) {
super(parent, toBlock, controller);
localController = (SortingAnimationController)controller;
}
protected void connectAnimatorAndArea() {
// 信息演示区域的演示器是infoAnimator,其他演示区域的演示器待定,因为当排序元素很多时不使用小区域的演
// 示器,因此这里也暂时没有设置小区域的演示器为 boxAnimator
infoArea.setAnimator(infoAnimator);
// 设置各演示器所分别使用的演示区域,不过同一时刻某个演示区域只有一个演示器使用,在选定要演示的排序算
// 法的同时,我们也会确定到底使用怎样的演示器
infoAnimator.setAnimationArea(infoArea);
heapAnimator.setAnimationArea(mainArea);
mergeAnimator.setAnimationArea(mainArea);
rectAnimator.setAnimationArea(mainArea);
boxAnimator.setAnimationArea(smallArea);
}
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);
JPanel tempPanel = new JPanel();
tempPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 40, 10));
// 创建选择排序算法的按钮
for (int i = 0; i < buttonName.length; i++) {
sortButton[i] = new JButton(buttonName[i]);
sortButton[i].addActionListener(new SortActionListener(buttonType[i]));
tempPanel.add(sortButton[i]);
}
parent.add(tempPanel);
}
protected void createAnimator() {
// 创建演示堆排序时所使用的演示器
heapAnimator = new HeapSortingAnimator(animationDriver);
heapAnimator.setStepDelay(localController.stepDelay);
heapAnimator.setUnitMoving(localController.unitMoving);
heapAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
// 创建演示合并排序时所使用的演示器
mergeAnimator = new MergeSortingAnimator(animationDriver);
mergeAnimator.setStepDelay(localController.stepDelay);
mergeAnimator.setUnitMoving(4*localController.unitMoving);
mergeAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
// 创建小区域所使用的演示器,通常是使用盒子视图的演示器
boxAnimator = new SortingArrayAnimator(animationDriver);
boxAnimator.setStepDelay(localController.stepDelay);
boxAnimator.setUnitMoving(localController.unitMoving);
boxAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
// 创建主区域在演示堆排序和合并排序以外的排序算法所使用的演示器,通常使用举行矩形条的演示器
rectAnimator = new SortingArrayAnimator(animationDriver);
rectAnimator.setStepDelay(localController.stepDelay);
rectAnimator.setUnitMoving(localController.unitMoving);
rectAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
// 创建提示排序时间、比较次数、移动次数、交换次数、选择次数等信息的演示器
infoAnimator = new SortingInfoAnimator();
infoAnimator.setSortingColor(localController.dataColor, localController.compareColor, localController.swapColor, localController.selectColor);
}
protected void useControllerParameter() {
animationDriver.setDelay(localController.animationDelay);
}
/**
* 使用数组 data 创建演示用的最初的视图
*/
public void createAnimationView(int[] data) {
// 注意在展示中可能不用 smallArea 中的展示,因此 smallAreaAnimator 可能是 null,但不允许 mainAreaAnimator 为 null,它应该
// 等于 rectAnimator, heapAnimator 或 mergeAnimator 之一
if (smallAreaAnimator != null && localController.showValue) {
smallAreaAnimator.createBoxAnimationScene(data, new Point(localController.startX, localController.smallStartY), localController.elementWidth, 0, Color.white);
} else {
smallAreaAnimator = null;
smallArea.setAnimator(null);
}
if (useHeapAnimator()) {
// 这时总有 mainAreaAnimator == heapAnimator
heapAnimator.createHeapAnimationScene(data, new Point(localController.startX, localController.mainMiddleY), localController.elementWidth, 0, Color.white);
heapAnimator.createHeapTreeAnimatorScene(data, new Point(localController.startX, localController.mainStartY), Math.max(24,localController.elementWidth), Color.white, localController.windowWidth-2*localController.startX, localController.mainStartY);
} else {
// 这时总有 mainAreaAnimator == rectAnimaotr || mainAreaAnimator == mergeAnimator
if (useMergeAnimator()) {
// 这时总有 mainAreaAnimator == mergeAnimator
mainAreaAnimator.createRectAnimationScene(data, new Point(localController.startX, localController.mainStartY), localController.elementWidth-localController.spacingWidth, localController.spacingWidth, AnimationView.darkGreen, localController.unitHeight, localController.showValue);
mergeAnimator.createMergeAnimatorScene(data, new Point(localController.startX, localController.mainMiddleY), localController.elementWidth, 0, Color.white);
} else {
if (localController.useDotViewInMainArea) mainAreaAnimator.createDotAnimationScene(data, new Point(localController.startX, localController.mainStartY), localController.windowWidth-2*localController.startX, localController.maxDataValue);
else 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 < buttonName.length; i++) sortButton[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();
if (useHeapAnimator()) {
heapAnimator.showSwapScene(firstIndex, secondIndex);
if (smallAreaAnimator != null) {
animationDriver.clear();
smallAreaAnimator.createSwapAnimation(firstIndex, secondIndex);
animationDriver.run();
smallAreaAnimator.swapElementView(firstIndex, secondIndex);
Animator.sleep(localController.stepDelay);
}
} else {
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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -