0

I have some class, extended from JPanel. Here it's code.

public class DrawingPanel extends JPanel{
    DrawingPanel(){
        mouseHandler=new MouseHandler(this);
        addMouseListener(mouseHandler);
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Point=mouseHandler.getPoint();
        g2 = (Graphics2D) g;
        if (Point!=null){
            drawStartPoint(Point.getX(),Point.getY());
        }
        drawField();
    }
    private void drawField(){
        g2.setColor(Color.BLACK);
        g2.setStroke(new BasicStroke(2));
        for (int i=1;i<Main.COLUMNS;i++){
            g2.draw(new Line2D.Double(15*i,0,15*i,450));
        }
        for (int i=1;i<Main.ROWS;i++){
            g2.draw(new Line2D.Double(0,15*i,450,15*i));
        }
    }
    private void drawStartPoint(double x, double y){
        g2.setStroke(new BasicStroke((5)));
        DrawingPoint point=new DrawingPoint(Point.getX(),Point.getY());
        startPoint=new Point2D.Double(point.getX(),point.getY());
        Ellipse2D circlePoint= new Ellipse2D.Double(point.getX(),point.getY(),Main.DIAMETR_OF_CIRCLE,Main.DIAMETR_OF_CIRCLE);
        g2.fill(circlePoint);
        g2.draw(circlePoint);
    }
    public void drawDirectLineUp(){
        startPointsList.add(startPoint);
        finishPointsList.add(new Point2D.Double(startPoint.getX(),startPoint.getY()-15));
    }
    private ArrayList<Point2D> startPointsList=new ArrayList<Point2D>();
    private ArrayList<Point2D> finishPointsList=new ArrayList<Point2D>();
    private Graphics2D g2;
    private MouseHandler mouseHandler;
    private Point2D Point;
    private Point2D startPoint;
}

The panel is repainted every time, I click on it. Here is code of mouseHandler class.

public class MouseHandler implements MouseListener
{
    MouseHandler(DrawingPanel thePanel)
    {
        this.panel=thePanel;
    }
    public void mouseClicked(MouseEvent event)
    {
        Point=event.getPoint();
        panel.repaint();
    }

//Here is some auto-generated methods.
    public Point2D getPoint()
    {
        Point2D thePoint=this.Point;
        this.Point=null;
        return thePoint;
    }
    private Point2D Point;
    private DrawingPanel panel;
}

As you can see, every time I click on panel, paintComponent method is called, which calls drawStartPoint method, where startPoint field gets some value. But when I call drawDirectLineUp method, from actionListener of button placed on main panel, startPoint is null. Why it has null value again? How can I avoid it?

public class MainForm{
    MainForm(){
        createUIComponents();
        //adding items to comboBoxes
        directLineOkButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0)
            {
                switch (directDirectionCombobox.getSelectedIndex()){
                    case 0: ((DrawingPanel)drawingPanel).drawDirectLineUp();  break;
                    case 1: ((DrawingPanel)drawingPanel).drawDirectLineUp();  break;
                    case 2: ((DrawingPanel)drawingPanel).drawDirectLineUp();  break;
                    case 3: ((DrawingPanel)drawingPanel).drawDirectLineUp();  break;
                }
            }
        });
    }
    public JPanel getMainPanel() {
        return mainPanel;
    }
    private void createUIComponents() {
           drawingPanel = new DrawingPanel();
    }
    private JPanel mainPanel;
    private JComboBox directDirectionCombobox;
    private JButton directLineOkButton;
    private JButton crossLineOkButton;
    private JComboBox crossLineComboBox;
    private JTextField crossLineSizeValue;
    private JButton clearButton;
    private JLabel directLineLabel;
    private JPanel directLinePanel;
    private JLabel crossLineLabel;
    private JPanel crossLinePanel;
    private JPanel okClearButtonPanel;
    private JTextField directLineSizeValue;
    private JButton saveButton;
    private JPanel drawingPanel;
}

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Main Form");
        frame.setContentPane(new MainForm().getMainPanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
    public static final int ROWS=31;
    public static final int COLUMNS=31;
    public static final int DIAMETR_OF_CIRCLE=3;
}

Here is a stack trace of exception.

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at DrawingPanel.drawDirectLineUp(DrawingPanel.java:57)
    at MainForm$1.actionPerformed(MainForm.java:28)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2028)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2351)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6414)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3275)
    at java.awt.Component.processEvent(Component.java:6179)
    at java.awt.Container.processEvent(Container.java:2083)
    at java.awt.Component.dispatchEventImpl(Component.java:4776)
    at java.awt.Container.dispatchEventImpl(Container.java:2141)
    at java.awt.Component.dispatchEvent(Component.java:4604)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4619)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4280)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4210)
    at java.awt.Container.dispatchEventImpl(Container.java:2127)
    at java.awt.Window.dispatchEventImpl(Window.java:2489)
    at java.awt.Component.dispatchEvent(Component.java:4604)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:717)
    at java.awt.EventQueue.access$400(EventQueue.java:82)
    at java.awt.EventQueue$2.run(EventQueue.java:676)
    at java.awt.EventQueue$2.run(EventQueue.java:674)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:690)
    at java.awt.EventQueue$3.run(EventQueue.java:688)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:687)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Finally, I add .form XMl file.

?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="MainForm">
  <grid id="27dc6" binding="mainPanel" layout-manager="FormLayout">
    <rowspec value="center:23px:noGrow"/>
    <rowspec value="top:3dlu:noGrow"/>
    <rowspec value="center:47px:noGrow"/>
    <rowspec value="top:3dlu:noGrow"/>
    <rowspec value="center:max(d;4px):noGrow"/>
    <rowspec value="top:3dlu:noGrow"/>
    <rowspec value="center:max(d;4px):noGrow"/>
    <rowspec value="top:7dlu:noGrow"/>
    <rowspec value="center:25px:noGrow"/>
    <rowspec value="top:174dlu:noGrow"/>
    <rowspec value="center:max(d;4px):noGrow"/>
    <colspec value="fill:d:noGrow"/>
    <colspec value="left:4dlu:noGrow"/>
    <colspec value="fill:452px:noGrow"/>
    <constraints>
      <xy x="20" y="20" width="741" height="453"/>
    </constraints>
    <properties/>
    <border type="none"/>
    <children>
      <component id="3b663" class="javax.swing.JLabel" binding="directLineLabel">
        <constraints>
          <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
          <forms/>
        </constraints>
        <properties>
          <text value="Direct Line"/>
        </properties>
      </component>
      <grid id="499e0" binding="directLinePanel" layout-manager="FormLayout">
        <rowspec value="center:d:grow"/>
        <colspec value="fill:98px:noGrow"/>
        <colspec value="left:4dlu:noGrow"/>
        <colspec value="fill:80px:grow"/>
        <colspec value="left:4dlu:noGrow"/>
        <colspec value="fill:max(d;4px):noGrow"/>
        <colspec value="left:4dlu:noGrow"/>
        <colspec value="fill:max(d;4px):noGrow"/>
        <constraints>
          <grid row="1" column="0" row-span="2" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
          <forms/>
        </constraints>
        <properties/>
        <border type="none"/>
        <children>
          <component id="c383d" class="javax.swing.JComboBox" binding="directDirectionCombobox">
            <constraints>
              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
              <forms/>
            </constraints>
            <properties>
              <enabled value="true"/>
            </properties>
          </component>
          <component id="17aa1" class="javax.swing.JTextField" binding="directLineSizeValue">
            <constraints>
              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
                <preferred-size width="150" height="-1"/>
              </grid>
              <forms defaultalign-horz="false"/>
            </constraints>
            <properties/>
          </component>
          <component id="44fc7" class="javax.swing.JButton" binding="directLineOkButton">
            <constraints>
              <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
              <forms/>
            </constraints>
            <properties>
              <text value="OK"/>
            </properties>
          </component>
        </children>
      </grid>
      <component id="5a571" class="javax.swing.JLabel" binding="crossLineLabel">
        <constraints>
          <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
          <forms/>
        </constraints>
        <properties>
          <text value="Cross Line"/>
        </properties>
      </component>
      <grid id="77f1a" binding="crossLinePanel" layout-manager="FormLayout">
        <rowspec value="center:d:grow"/>
        <colspec value="fill:98px:noGrow"/>
        <colspec value="left:4dlu:noGrow"/>
        <colspec value="fill:80px:grow"/>
        <colspec value="left:4dlu:noGrow"/>
        <colspec value="fill:max(d;4px):noGrow"/>
        <colspec value="left:4dlu:noGrow"/>
        <colspec value="fill:max(d;4px):noGrow"/>
        <constraints>
          <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
          <forms/>
        </constraints>
        <properties/>
        <border type="none"/>
        <children>
          <component id="32368" class="javax.swing.JComboBox" binding="crossLineComboBox">
            <constraints>
              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
              <forms/>
            </constraints>
            <properties/>
          </component>
          <component id="dbf23" class="javax.swing.JTextField" binding="crossLineSizeValue">
            <constraints>
              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
                <preferred-size width="150" height="-1"/>
              </grid>
              <forms defaultalign-horz="false"/>
            </constraints>
            <properties/>
          </component>
          <component id="c5c8a" class="javax.swing.JButton" binding="crossLineOkButton">
            <constraints>
              <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
              <forms/>
            </constraints>
            <properties>
              <text value="OK"/>
            </properties>
          </component>
        </children>
      </grid>
      <grid id="53bbc" binding="okClearButtonPanel" layout-manager="FormLayout">
        <rowspec value="center:d:noGrow"/>
        <colspec value="fill:d:noGrow"/>
        <colspec value="left:4dlu:noGrow"/>
        <colspec value="fill:max(d;4px):noGrow"/>
        <constraints>
          <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
          <forms/>
        </constraints>
        <properties>
          <enabled value="false"/>
        </properties>
        <border type="none"/>
        <children>
          <component id="41ba7" class="javax.swing.JButton" binding="saveButton">
            <constraints>
              <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
              <forms/>
            </constraints>
            <properties>
              <text value="Save"/>
            </properties>
          </component>
          <component id="a6bf6" class="javax.swing.JButton" binding="clearButton">
            <constraints>
              <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
              <forms/>
            </constraints>
            <properties>
              <text value="Clear"/>
            </properties>
          </component>
        </children>
      </grid>
      <grid id="2e94e" binding="drawingPanel" custom-create="true" layout-manager="FormLayout">
        <rowspec value="center:d:grow"/>
        <colspec value="fill:d:grow"/>
        <constraints>
          <grid row="0" column="2" row-span="11" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
          <forms/>
        </constraints>
        <properties>
          <background color="-1"/>
        </properties>
        <border type="none"/>
        <children/>
      </grid>
    </children>
  </grid>
</form>

Strange bug

4

4 回答 4

1

Look like instantiation problem, DrawingPanel was created twice. Also, method createUIComponents was called twice - once in constructor and by MainForm.form (looks like it is standard method or something like this), so we had two separate instances.

The solution is removing redundant createUIComponents call

于 2013-09-24T08:40:09.090 回答
0
   public void drawDirectLineUp(){
        if(startPoint!=null){  //Please ensure do you have initialized startPoint properly .
            startPointsList.add(startPoint);
            finishPointsList.add(new Point2D.Double(startPoint.getX(),startPoint.getY()-15));
        }               
   }
于 2013-09-23T09:46:38.577 回答
0

Is it possible, that the variable drawingPanel in the ActionListener of your button does not point to the same DrawingPanel you clicked?

And it's true that if you first click your button before you click into your panel, the variable startPoint is still null.

于 2013-09-23T10:32:08.157 回答
0

Every time paintComponent is called, it is calling mouseHandler.getPoint(), which is setting Point to null. This value is then assigned to startPoint.

paintComponent can be called for any number of reasons, many of which you don't control.

You be better off adding the startPoint directly to your list (when the mouse is clicked), repainting the component each time

Do you realise, your example doesn't appear to be adding anything to the frame and would probably throw a NullPointerException

于 2013-09-23T10:43:36.193 回答