I did it for my bachelor, I did it like this (this is not perfect, but it could help you):
(I removed some irrelevant methods / functions from the code below. Basically, to illustrate how I rendered it. You can replace the GRectangle class with simple java.awt.Point, for example.)
The initialization method gives you an example of how you can find the maximum and minimum value of the data so that you know how to convert the data datavalues ββ=>.
public class DotVisualisation extends Visualisation { private ArrayList<GRectangle> m_points; private Comparable[] m_data; private Comparable m_maxValue; private Comparable m_minValue; private int MAX_HEIGHT; // max height in pixels of visualization /** * Creates a new DotVisualisation.<br> * <br> * This class is a runnable JComponent that will visualize data as a function. * The visualisation will plot the data with X and Y coordinates on the window. * The X coordinate of the point is index of the dataelement. * The Y coordinate of the point is relative to the value of the dataelement.<br> * <br> * This visualisation should be used for medium and large arrays. * * @author David Nysten */ public DotVisualisation() { m_points = new ArrayList<GRectangle>(); MAX_HEIGHT = 150; } /** * Returns the maximum supported dimension by this visualisation. * * @return The supported dimension. */ public static int getSupportedDimension() { return 1; } @Override public Dimension getMaximumSize() { return getPreferredSize(); } @Override public Dimension getPreferredSize() { return new Dimension(m_points.size() + 2, MAX_HEIGHT + 6); } @Override public Dimension getMinimumSize() { return getPreferredSize(); } @Override public void paintComponent(Graphics g) { for(int i = 0; i < m_points.size(); ++i) m_points.get(i).paintComponent(g); } private void swap(int index, int index2) { // See below } private void initialise() { findMinimum(); findMaximum(); m_points.clear(); double multiplier; int x = 0, y = 0, h; for(int i = 0; i < m_data.length; ++i) { if(m_data[i].compareTo(-1) <= 0) h = 0; else { Integer value = (Integer) m_data[i]; Integer min = (Integer) m_minValue; Integer diff = (Integer) m_maxValue - min; multiplier = MAX_HEIGHT / diff.doubleValue(); h = (int) ((value - min) * multiplier); } y = (int) (MAX_HEIGHT - h); GRectangle r = new GRectangle(x, y, 1, 1); // 1, 1 = width and height r.setColor(Color.BLACK); m_points.add(r); ++x; } } private void findMaximum() { Comparable max = null; if(m_data.length > 0) { max = m_data[0]; for(int i = 1; i < m_data.length; ++i) if(m_data[i].compareTo(max) > 0) max = m_data[i]; } m_maxValue = max; } private void findMinimum() { Comparable min = null; if(m_data.length > 0) { min = m_data[0]; for(int i = 1; i < m_data.length; ++i) if(m_data[i].compareTo(min) < 0) min = m_data[i]; } m_minValue = min; } }
Keep this in mind: Rendering integers from 0 to 150 at a height of 150 pixels is simple. Rendering a set of integers between the values ββ565 and 3544545 at a height of 150 is slightly smaller.
PS: the code uses the element index in inputarray as the X coordinate.
PS: the class stores a reference to the variable inputarray (variable m_data), but, of course, it is not needed, you only need to initialize it with your glasses.
PS: My Visualization class, which expands with all visualizations, is basically JPanel.
PS: the above code is written for positive integers, so you probably need extra coding to handle negative integers;).
Then, to visualize the actions of the algorithm, I used the observer pattern. An algorithm, such as bubblesort, looked like this:
for(int i = 0; i < size(); ++i) for(int j = 1; j < size(); ++j) if(greaterThan(j - 1, j)) swap(j - 1, j);
If the swap function was defined as follows (simplified version):
protected void swap(int index1, int index2) { if(index1 != index2) { incrementSwap(); // counting swaps and visualizing counter m_command.clear(); m_command.setAction(Action.SWAP); m_command.addParameter(index1); m_command.addParameter(index2); setChanged(); notifyObservers(m_command); E temp = m_data[index1]; m_data[index1] = m_data[index2]; m_data[index2] = temp; } }
Where I notified my observers (visualization) that the swap occurred on index1 and index2. The m_command variable is an instance of the Command class (he wrote it), which is just a wrapper for the information needed for visualization. Which: the action that occurred, and related information (for example, indexes for the swap action).
Thus, during visualization, I changed GRectangles to these indices, as well as their X-coordinates;
private void swap(int index, int index2) { if(index == index2) return; GRectangle r1 = m_points.get(index); GRectangle r2 = m_points.get(index2); int tempX = r1.getX(); r1.setLocation(r2.getX(), r1.getY()); r2.setLocation(tempX, r2.getY()); m_points.set(index, r2); m_points.set(index2, r1); }
You can add these lines:
try { Thread.sleep(100); } catch(InterruptedException ignore) {}
so that the thread overslept 100 ms before continuing. This can come in handy if you render it too quickly.
So, for an array with random integer values, it might look like this:

And after sorting: (Of course, this is not a straight line, because in this case the values ββin the input symbol were randomly generated)

So, if you need - like me - to allow several algorithms to work with the same visualization, I can recommend that you separate the visualization class and the algorithm class and work with the observer pattern to update the visualization whenever an action occurs (set, swap ...).
And then you can create something similar for comparison;
http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany_zps63269d2a.png http://i445.photobucket.com/albums/qq179/ultddave/DotVisualizationMany2_zps65e96fa9.png
Good luck