2012-10-26 40 views
1

所以我正在爲我的課程開發一個GUI項目,而且我有點卡住了。我的問題與我的GUI方面有關,所以我想你可以忽略與排序有關的其他方法。截至目前,我主要關心的是讓GUI工作。不過,我一直運行到一個錯誤,一個空指針異常確切的說:Java GUI NullPointerException和Canvas類

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 Docs,但我仍然不明白我做錯了什麼。這裏是我的代碼:

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

回答

3

這不是必需的;

picture.paint(picture.getGraphics()); 

getGraphics將返回null如果組件尚未被畫本身。您應該避免使用這種方法,它僅僅是當前組件的圖形狀態(在你的情況是什麼)的快照

你不控制烤漆工藝,這是下降到重繪管理器。您可以通過repaint方法請求更新。有通過Painting in AWT and Swing

您應該避免混合重物(Canvas)的&重量輕組分(JFrame的)在一起,如果可能的話,你應該Swing組件

+0

有一個輕量級組件,我可以使用類似帆布顯示我需要的形象呢? – Mike

+0

'JPanel'通常是首選 – MadProgrammer

+0

我明白了,非常感謝你! – Mike

1

調用paint()直接會導致你從這個出現意外的行爲,使用repaint()代替:

picture.repaint(); 
+0

哪條線堅持我需要更換與閱讀? – Mike

+0

好吧,現在它只顯示我的照片和我的按鈕,它佔據了整個窗口。沒有其他面板顯示..我該怎麼辦? – Mike

+0

您正在使用'BorderLayout'並將按鈕添加到您的容器的CENTER位置,該位置將展開以填充容器的整個區域。您需要計劃您的佈局以按照您希望的方式顯示組件。參見[視覺引導佈局管理器(http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html) – Reimeus