Over the course of the past month I've worked on a little visualizer to show how different algorithms are sorted. I'm pretty happy with how it turned out but would be interested in any feedback pertaining to the design of it or the coding.
I'm still a bit of a novice to Swing, so I'd love some feedback on my usage:
public class SortPanel extends JPanel {
private ArrayList<Integer> list;
private ArrayList<Colors> colorList;
private int hPad;
private int hRatio = 10; // ratio between width of bars and padding
private int width;
private int vPad = 5;
private int index;
private int line;
private float vScale;
private String name, message;
public SortPanel(String name) {
super();
list = new ArrayList<Integer>();
colorList = new ArrayList<Colors>();
this.name = name;
message = "";
index = 0;
line = 0;
}
/*
...
Variety of setters and getters to manipulate the list of numbers
...
*/
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.clearRect(0, 0, this.getWidth(), this.getHeight());
g2d.drawString(name, 5, this.getHeight() - 30);
g2d.drawString(message,5,this.getHeight() - 15);
if (this.getListSize() > 0) {
hPad = this.getWidth() / ((hRatio + 1) * list.size() + 1);
vScale = (this.getHeight() - 2 * vPad - g2d.getFont().getSize() - 50)
/ (float) list.get(this.getMaxIndex());
g2d.drawRect(0, 0, this.getWidth(), this.getHeight());
width = hRatio * hPad;
int y = vPad + 20;
g2d.setColor(Colors.TARGET.get());
g2d.drawLine(0, y+Math.round(line*vScale), this.getWidth(), y+Math.round(line*vScale));
for (int i = 0; i < list.size(); i++) {
int x = hPad * ((hRatio + 1) * i + 1);
g2d.setColor(colorList.get(i).get());
g2d.fillRect(x, y, width, Math.round(list.get(i) * vScale));
if (i == index) { // index marker
g2d.setColor(Color.RED);
g2d.fillOval((2 * x + width) / 2 - 5, 5, 10, 10);
}
}
}
}
}
This was also my first time using an enum
. I wanted to make it easier to quickly get the Color
I needed. Does this way provide less overhead and work more efficiently?
import java.awt.Color;
public enum Colors {
INACTIVE(191, 191, 191), SORTED(87, 232, 14), TARGET(255, 0, 0), ACTIVE(8,8,8), LOWER(12,94,245), UPPER(205,21,0);
private final Color col;
Colors(int r, int g, int b) {
col = new Color(r, g, b);
}
public Color get() {
return col;
}
}
I also used Thread
s for the first time here, so this is probably one of my main areas to look at.
public QuickSortThread(SortPanel sp, long msdelay) {
super(sp, msdelay);
sp.setIndex(-1);
}
public int partition(ArrayList<Integer> nums, int a, int b) {
if (started) {
int pivot = nums.get(b);
sp.setLine(pivot);
sp.setColorRange(a, b, Colors.ACTIVE);
sp.setColor(b, Colors.TARGET);
int greater = a;
sp.setMessage("Moving elements before/after index " + greater
+ " if they are < or > " + pivot + ".");
for (int i = a; i < b && started; i++) {
sp.setIndex(i);
while (paused) {
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
if (nums.get(i) < pivot) {
sp.setColor(i, Colors.LOWER);
sp.swap(i, greater);
greater++;
sp.setMessage("Moving elements before/after index "
+ greater + " if they are < or > " + pivot
+ ".");
} else {
sp.setColor(i, Colors.UPPER);
}
sp.repaint();
try {
Thread.sleep(msdelay);
} catch (Exception ex) {
ex.printStackTrace();
}
}
sp.swap(greater, b);
sp.repaint();
try {
Thread.sleep(msdelay);
} catch (Exception ex) {
ex.printStackTrace();
}
return greater;
}
return -1;
}
public void quickSort(ArrayList<Integer> nums, int a, int b) {
sp.setColorRange(0, Colors.INACTIVE);
sp.repaint();
if (a < b + 1 && started) {
int pivot = partition(nums, a, b);
quickSort(nums, a, pivot - 1);
quickSort(nums, pivot + 1, b);
}
}
public void run() {
quickSort(list, 0, list.size() - 1);
if (started) {
sorted = true;
sp.setLine(0);
sp.setMessage("Sorted!");
sp.setColorRange(0, Colors.SORTED);
sp.setIndex(-1);
sp.repaint();
}
if (checkAllSorted() && started) {
MainWindow.this.start();
}
}
}
One thing I couldn't figure out was reducing the repeated Thread.sleep()
blocks to methods. When I did so they stopped working. General OOP advice is also appreciated.