Question

So I am working on a GUI project for my class and I am a bit stuck. My problem has to do with my GUI aspect so I guess you could ignore the other methods having to do with the sorting. As of now, my main concern is just getting the GUI working. However, I keep running into an error, a null pointer exception to be exact:

Java.lang.NullPointerException
    at SortDriver$SortCanvas.paint(SortDriver.java:253)
    at SortDriver.init(SortDriver.java:197)
    at sun.applet.AppletPanel.run(AppletPanel.java:436)
    at java.lang.Thread.run(Thread.java:679)

After reading though my code, I think I narrowed it down to the my SortCanvas class. I never used it before but it was part of the stub my professor gave to us. That is to say that it works correctly and displays the image correctly but it looks like my implementation is incorrect however. Could someone help me figure out how to implement my SortCanvas "picture" correctly please? I read over the Java Docs for Canvas and I still don't understand what I am doing wrong. Here is my code:

import java.awt.*;
import java.applet.Applet;
import javax.swing.*;
import java.awt.event.*;

public class SortDriver extends Applet {

private int array[];  // array to be sorted
private int limit = 1000;  // size of array to be sorted - you may have to make
// this bigger for faster sorts
private int largestNum; // need to know for color scaling purposes in paint()

// flag to tell paint() whether to paint a single location or the whole array
private enum PaintType {ALL, SINGLE};
private PaintType doPaint = PaintType.ALL;

private int index = -1;  // index of single array location to be painted

//this listener object responds to button events
private ButtonActionListener buttonListener;

//button to start the sort
private JButton sortButton;

//basic window frame
private JFrame mainFrame;

//layouts
private BorderLayout initialLayout;
private FlowLayout northLayout;
private BorderLayout centerLayout;
private BorderLayout southLayout;

//basic panel for window frame
private JPanel initialPanel;
//panels for window layout
private JPanel northPanel;
private JPanel centerPanel;
private JPanel southPanel;
//panels for radio buttons
private JPanel radioOrderPanel;
private JPanel radioSortPanel;
private JPanel radioColorPanel;

//north panel header labels
private JLabel topTitleLabel;
private JLabel bottomTitleLabel;
private JLabel arraySizeLabel;

//radio buttons for list order (radioOrderButton)
//random set, ordered set, reverse set
private JRadioButton rOB1, rOB2, rOB3;
//radio buttons for sort type (radioSortButton)
//bubblesort, insertionsort, mergesort, quicksort
private JRadioButton rSB1, rSB2, rSB3, rSB4;
//radio buttons for color choice (radioColorButton)
//green, red, white, blue
private JRadioButton rCB1, rCB2, rCB3, rCB4;

//radio button groups for each radio panel
private ButtonGroup orderGroup, sortGroup, colorGroup;

//text field for size of the array
private JTextField arraySizeTextField;

// the picture of the sort will appear on this canvas
private SortCanvas picture;
private final int pictureWidth = 500;  // size of the sort bar 1001
private final int pictureHeight = 50;

public void init() {

    buttonListener = new ButtonActionListener();

    array = new int[limit];
    // load the array
    largestNum = array[0] = (int) (Math.random()*1000000.0);
    for (int i=1; i<limit; i++) {
        array[i] = (int) (Math.random()*1000000.0);
        // also keep track of the largest so that we can scale by it in paint()
        if (array[i] > largestNum) largestNum = array[i]; 
    }

    //set up the main frame
    mainFrame = new JFrame();
    initialPanel = (JPanel) mainFrame.getContentPane();
    initialLayout = new BorderLayout();
    mainFrame.setResizable(false);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setSize(650, 750);
    initialPanel.setLayout(initialLayout);

    //set up north panel
    northPanel = new JPanel();
    northLayout = new FlowLayout();
    topTitleLabel = new JLabel("SortIt!");
    bottomTitleLabel = new JLabel("A program by Mike Sevilla");
    northPanel.setLayout(northLayout);
    northPanel.add(topTitleLabel, BorderLayout.NORTH);
    northPanel.add(bottomTitleLabel, BorderLayout.NORTH);
    initialPanel.add(northPanel, BorderLayout.NORTH);

    //set up center panel
    centerPanel = new JPanel();
    centerLayout = new BorderLayout();
    centerPanel.setLayout(centerLayout);
    //place array size label
    arraySizeLabel = new JLabel("Size:");
    //place array size text field w/ space for 5 chars
    arraySizeTextField = new JTextField("", 5);
    //place sort button
    sortButton = new JButton("Sort it!");
    // the listener is triggered when the button is clicked
    sortButton.addActionListener(buttonListener);
    centerPanel.setLayout(centerLayout);
    //place sort bar on top of center layout
    picture = new SortCanvas();
    centerPanel.add(picture, BorderLayout.CENTER);
    centerPanel.add(arraySizeLabel, BorderLayout.CENTER);
    centerPanel.add(arraySizeTextField, BorderLayout.CENTER);
    centerPanel.add(sortButton, BorderLayout.CENTER);
    initialPanel.add(centerPanel, BorderLayout.CENTER);

    //set up south panel
    southPanel = new JPanel();
    southLayout = new BorderLayout();
    southPanel.setLayout(southLayout);
    //set radio buttons and format layouts
    radioOrderPanel = new JPanel();
    radioOrderPanel.setLayout(new BoxLayout(radioOrderPanel, BoxLayout.Y_AXIS));
    radioSortPanel = new JPanel();
    radioSortPanel.setLayout(new BoxLayout(radioSortPanel, BoxLayout.Y_AXIS));
    radioColorPanel = new JPanel();
    radioColorPanel.setLayout(new BoxLayout(radioColorPanel, BoxLayout.Y_AXIS));
    //define radio buttons
    rOB1 = new JRadioButton("Random Order", true);
    rOB1.addActionListener(buttonListener);
    radioOrderPanel.add(rOB1);

    rOB2 = new JRadioButton("In Order", false);
    rOB2.addActionListener(buttonListener);
    radioOrderPanel.add(rOB2);

    rOB3 = new JRadioButton("In Reverse", false);
    rOB3.addActionListener(buttonListener);
    radioOrderPanel.add(rOB3);

    rSB1 = new JRadioButton("Bubble Sort", true);
    rSB1.addActionListener(buttonListener);
    radioSortPanel.add(rSB1);

    rSB2 = new JRadioButton("Insertion Sort", false);
    rSB2.addActionListener(buttonListener);
    radioSortPanel.add(rSB2);

    rSB3 = new JRadioButton("Merge Sort", false);
    rSB3.addActionListener(buttonListener);
    radioSortPanel.add(rSB3);

    rSB4 = new JRadioButton("Quick Sort", false);
    rSB4.addActionListener(buttonListener);
    radioSortPanel.add(rSB4);

    rCB1 = new JRadioButton("Green", true);
    rCB1.addActionListener(buttonListener);
    radioColorPanel.add(rCB1);

    rCB2 = new JRadioButton("Red", false);
    rCB2.addActionListener(buttonListener);
    radioColorPanel.add(rCB2);

    rCB3 = new JRadioButton("White", false);
    rCB3.addActionListener(buttonListener);
    radioColorPanel.add(rCB3);

    rCB4 = new JRadioButton("Blue", false);
    rCB4.addActionListener(buttonListener);
    radioColorPanel.add(rCB4);

    //add radio buttons to a button group
    orderGroup = new ButtonGroup();
    orderGroup.add(rOB1);
    orderGroup.add(rOB2);
    orderGroup.add(rOB3);       
    sortGroup = new ButtonGroup();
    sortGroup.add(rSB1);
    sortGroup.add(rSB2);
    sortGroup.add(rSB3);
    sortGroup.add(rSB4);
    colorGroup = new ButtonGroup();
    colorGroup.add(rCB1);
    colorGroup.add(rCB2);
    colorGroup.add(rCB3);
    colorGroup.add(rCB4);
    initialPanel.add(southPanel, BorderLayout.NORTH);

    picture.paint(picture.getGraphics());
    mainFrame.setVisible(true);
}

// this object is triggered whenever a button is clicked
private class ButtonActionListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {

        // find out which button was clicked 
        Object source = event.getSource();

        // start sort button was clicked
        if (source == sortButton) {
            // call the sort
            doBubblesort();
        }
        // called when user hits return in text field
        if (source == arraySizeTextField) {
            int size = Integer.parseInt(arraySizeTextField.getText());
        }
    }    
}

private void doBubblesort() {
    int temp;

    // this is just bubblesort
    for (int i=0; i<limit-1; i++) {
        for (int j=0; j<limit-1-i; j++) {
            if (array[j]>array[j+1]) {
                temp = array[j]; array[j] = array[j+1]; array[j+1] = temp;

                // redraw only locations j and j+1
                doPaint = PaintType.SINGLE;  // try changing this to ALL and see what happens
                index = j; 
                picture.paint(picture.getGraphics());
                index = j+1; 
                picture.paint(picture.getGraphics());
            }
        }
    }
}      

class SortCanvas extends Canvas {
    // this class paints the sort bar 

    SortCanvas() {
        setSize(pictureWidth, pictureHeight);
        setBackground(Color.white);
    }

    public void paint(Graphics g) {

        if (doPaint == PaintType.ALL) {
            // paint whole array - this takes time so it shouldn't be done too frequently
            setBackground(Color.white);
            g.setColor(Color.white);
            g.fillRect(0, 0, pictureWidth, pictureHeight);

            for (int i=0; i<limit; i++) {
                // the larger the number, the brighter green it is
                // green is between 0.0 and 1.0
                // divide by the largest number to get a value between 0 and 1
                float green = (float)(array[i]/(float)largestNum);

                // clamp if necessary - it shouldn't be
                if (green<0f) green = 0f;
                if (green>1f) green = 1f;

                g.setColor(new Color(0.0f, green, 0.0f));
                // array location 0 is painted at left; 
                //   array location limit-1 is painted to right
                //this is a single vertical line in the bar
                g.drawLine((int)(i*pictureWidth/limit), 0, 
                        (int)(i*pictureWidth/limit), pictureHeight);
            }
        }
        else {
            // just paint one location on the bar
            float green = (float)(array[index]/(float)largestNum);
            if (green<0f) green = 0f;
            if (green>1f) green = 1f;
            g.setColor(new Color(0.0f, green, 0.0f));
            g.drawLine((int)(index*pictureWidth/limit), 0, 
                    (int)(index*pictureWidth/limit), pictureHeight);
        }   
    }
}
}
Was it helpful?

Solution

This is not required;

picture.paint(picture.getGraphics());

getGraphics will return null if the component has not yet being painted itself. You should avoid using this method, it is simply a snap shot of the current components graphical state (which in your case is nothing)

You don't control the paint process, that's down to the repaint manager. You can request updates via the repaint methods. Have a read through Painting in AWT and Swing

You should avoid mixing heavy weight (Canvas) & light weight components (JFrame) together, where possible, you should stick with Swing components

OTHER TIPS

Calling paint() directly can lead to unexpected behavior as you are see from this, use repaint() instead:

picture.repaint();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top