1

所以我正在为我的班级制作一个 GUI 项目,但我有点卡住了。我的问题与我的 GUI 方面有关,所以我想您可以忽略与排序有关的其他方法。到目前为止,我主要关心的是让 GUI 正常工作。但是,我一直遇到错误,确切地说是空指针异常:

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)

在阅读了我的代码之后,我认为我将其范围缩小到了我的 SortCanvas 类。我以前从未使用过它,但它是我的教授给我们的存根的一部分。也就是说它可以正常工作并正确显示图像,但看起来我的实现不正确。有人可以帮我弄清楚如何正确实现我的 SortCanvas“图片”吗?我阅读了 Canvas 的 Java 文档,但我仍然不明白我做错了什么。这是我的代码:

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);
        }   
    }
}
}
4

2 回答 2

3

这不是必需的;

picture.paint(picture.getGraphics());

getGraphicsnull如果组件本身还没有被绘制,将返回。您应该避免使用此方法,它只是当前组件图形状态的快照(在您的情况下什么都不是)

您无法控制绘制过程,这取决于重绘管理器。您可以通过这些repaint方法请求更新。阅读AWT 和 Swing 中的绘画

您应该避免将重量级(Canvas)和轻量级组件(JFrame)混合在一起,在可能的情况下,您应该坚持使用 Swing 组件

于 2012-10-26T19:12:32.860 回答
1

如您所见,直接调用paint()可能会导致意外行为,请repaint()改用:

picture.repaint();
于 2012-10-26T19:05:22.090 回答