Search code examples
javaswingarraylistgraphics2d

Using an arrayList as the y coordinate in graphics2d


I'm trying to create a way of visualizing arraysorting by creating a form of "bar graph" by using line2d/graphics2d. The idea is to have the array index on the x axis and then having the value on the y and updating it while using different sorting methods. So I'm trying to use an arrayList to store the y values and then using a for loop in the paint method to draw all the lines, but it seems whenever I try and use repaint it resets my arrayList, so how do I do this?

Here's the code I'm using:

import javax.swing.*;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.Random;

public class Frame_Main extends JFrame {

    private JPanel screen = new Screen();
    private Screen _screen = new Screen();

    private int rndMaxRange = 100;
    private int maxArraySize = 50;

    // TODO Make sure static is really needed
    public static ArrayList<Integer> array = new ArrayList<>();

    public Frame_Main() {
        this.setSize(700, 500);
        this.setVisible(true);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.add(screen);
    }

    public static void main(String[] args) {
        Frame_Main m = new Frame_Main();

        m.randomizeArray(array);
        m.refreshVisuals(array);
    }

    public void refreshVisuals(ArrayList<Integer> arrayList) {

        _screen.setArrayList(arrayList);
        _screen.repaint();

        System.out.println("Refreshed drawing. Screen Array Size: " + _screen.lineArrayList.size());
    }

    public void randomizeArray(ArrayList<Integer> arrayList) {
        arrayList.clear();
        Random rnd = new Random();

        for (int i = 0; i < maxArraySize; i++) {
            arrayList.add(rnd.nextInt(rndMaxRange) + 1);
        }

        System.out.println("Created an array with the size: " + arrayList.size());
    }
}

class Screen extends JPanel {

    public ArrayList<Integer> lineArrayList = new ArrayList<>();

    // private int canvasWidth = Frame_Main.WIDTH;
    private int lineWidth;

    public void setArrayList(ArrayList<Integer> arrayList) {
        lineArrayList.addAll(arrayList);
    }

    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;

        lineWidth = 3;
        g2.setStroke(new BasicStroke(lineWidth));

        System.out.println("lineArrayList Size: " + lineArrayList.size());

        int x = 0;

        for (int i : lineArrayList) {
            g2.draw(new Line2D.Float(x, x, 0, i));
            x = x + lineWidth;
        }
    }
}

Solution

  • You never add your _screen variable to the GUI, it is never displayed, and so calling repaint() on it does nothing.

    So for starteres, change

    this.add(screen);
    

    to:

    add(_screen);
    

    Other unrelated issues:

    • You should override the JPanel's paintComponent method, not its paint method
    • You should call the super's painting method first thing within your override.

    e.g., something like...

    import java.awt.BasicStroke;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.Stroke;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class MyScreen extends JPanel {
        private static final int PREF_W = 700;
        private static final int PREF_H = 500;
        private static final int LINE_WIDTH = 5;
        private static final Stroke STROKE = new BasicStroke((float) LINE_WIDTH);
        private static final int MAX_DATA_SIZE = 50;
        private static final int MAX_RANGE = 400;
        private List<Integer> displayData = new ArrayList<>();
        private Random random = new Random();
    
        public MyScreen() {
            for (int i = 0; i < MAX_DATA_SIZE; i++) {
                displayData.add(random.nextInt(MAX_RANGE) + 1);
            }
        }
    
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            }
            return new Dimension(PREF_W, PREF_H);
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            // to do house-keeping painting
            super.paintComponent(g);
    
            // to smooth out graphics
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
            if (displayData == null) {
                return;
            }
    
            g2.setStroke(STROKE);
            int x = 0;
            for (Integer i : displayData) {
                g2.drawLine(x, x, 0, i);
                x += LINE_WIDTH;
            }
        }
    
    
        private static void createAndShowGui() {
            MyScreen mainPanel = new MyScreen();
    
            JFrame frame = new JFrame("My Screen");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }