2014-09-05 92 views
0

我已經用java編程了大約4到5個月了,而且我沒有什麼可抱怨的。這很棒。雖然我還處於學習階段,但我已經走了很長時間了,我已經投入了很多時間。如何拆分計算器類?

好的,我做了一個Calculator類。通常情況下,我對多態性(OO)工作非常熟練,並嘗試儘可能地創建相關類。

只是這一次,我碰上與計算器的按鈕的問題,當我Calculator類分離成分離的類..

I.E. :我想要做的是,製作一個Calculator類,一個ButtonHandler類和一個ActionListener類,並且不寫這麼多Operants我也想要一個ScriptEngineManager類(js)。

但是,當我過了計算器java類分成這些類,這些按鈕會沒有反應,我得到:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
    at calc_758D6.NumButtonActionListener.actionPerformed(NumButtonActionListener.java:29) 
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) 
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346) 
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) 
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) 
    at java.awt.Component.processMouseEvent(Component.java:6527) 
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321) 
    at java.awt.Component.processEvent(Component.java:6292) 
    at java.awt.Container.processEvent(Container.java:2234) 
    at java.awt.Component.dispatchEventImpl(Component.java:4883) 
    at java.awt.Container.dispatchEventImpl(Container.java:2292) 
    at java.awt.Component.dispatchEvent(Component.java:4705) 
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898) 
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533) 
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462) 
    at java.awt.Container.dispatchEventImpl(Container.java:2278) 
    at java.awt.Window.dispatchEventImpl(Window.java:2739) 
    at java.awt.Component.dispatchEvent(Component.java:4705) 
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746) 
    at java.awt.EventQueue.access$400(EventQueue.java:97) 
    at java.awt.EventQueue$3.run(EventQueue.java:697) 
    at java.awt.EventQueue$3.run(EventQueue.java:691) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86) 
    at java.awt.EventQueue$4.run(EventQueue.java:719) 
    at java.awt.EventQueue$4.run(EventQueue.java:717) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75) 
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:716) 
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

但我發現這個奇怪,因爲我用了「實現的ActionListener」,同時也做了我用'擴展計算器'

所以對象應該正確鏈接,才能正常工作,對嗎?

如果有人可以告訴我如何將這個Calculator類分成不同的類,那就太好了。

這是我的代碼:

  package calculator; 

      import java.awt.BorderLayout; 
      import java.awt.Container; 
      import java.awt.ComponentOrientation; 
      import java.awt.Dimension; 
      import java.awt.FlowLayout; 
      import java.awt.GridLayout; 
      import java.awt.Insets; 
      import java.awt.event.ActionEvent; 
      import java.awt.event.ActionListener; 
      import javax.script.ScriptEngine; 
      import javax.script.ScriptEngineManager; 
      import javax.script.ScriptException; 
      import javax.swing.BorderFactory; 
      import javax.swing.JApplet; 
      import javax.swing.JButton; 
      import javax.swing.JComponent; 
      import javax.swing.JFrame; 
      import javax.swing.JTextField; 
      import javax.swing.JLabel; 
      import javax.swing.JOptionPane; 
      import javax.swing.JPanel; 
      import javax.swing.border.EmptyBorder; 


      public class Calculator extends JApplet { 


       // ;which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. 
       public static final long serialVersionUID = 1; 
       // boolean A flag whether the text in the antwoordCalculatieEntryfield is the result of a calculation 
       private boolean antwoordCalculatieEntryfield; 
       //Container The container of our app 
       private Container con; 
       //JPanel The 'root' panel 
       private JPanel panel; 
       //JTextField The field in which the calculations are created 
       private JTextField entryField; 
       //double Memory 
       private double defaultMemory = 0; 
       //new 
       private Menu editDropDownMenu; 
       private Menu viewDropDownMenu; 
       private Menu helpDropDownMenu; 
       private MenuBar menuBalk; 
       private MenuItem optie1, optie2, optie3; 
       private MenuItem viewOptie1, viewOptie2; 
       private MenuItem helpOptie; 

       /** 
       * This method is called when the app is an applet 
       * This will prepare for the app being used as an in-browser applet 
       */ 
       public void init() { 
        this.con = getContentPane(); 

        createGUI(); 
       } 

       /** 
       * This method is called when the app is started from the jar file 
       * This will prepare the app for being used as a standalone application 
       */ 
       public void go() { 
        // Create a frame and set the container 
        JFrame frame = new JFrame(); 
        menuBalk = new MenuBar(); 
        editDropDownMenu = new Menu ("Edit"); 
        viewDropDownMenu = new Menu ("View"); 
        helpDropDownMenu = new Menu ("Help"); 


        this.con = frame.getContentPane(); 

        // Build the GUI 
        createGUI(); 

        frame.setLocation(400,400); 
        frame.setResizable(false); 
        frame.setMenuBar(menuBalk); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        frame.setSize(300, 250); 
        frame.setVisible(true); 

       } 

       /** 
       * Create the GUI 
       */ 
       private void createGUI() { 
        panel = new JPanel(new BorderLayout()); 

        entryField = new JTextField("0."); 
        panel.add(entryField, BorderLayout.NORTH); 

        JPanel buttonPanel = new JPanel(new BorderLayout(10,0)); 

        // Build the different panels 
        buttonPanel.add(buildNorthPanel(), BorderLayout.NORTH); 
        buttonPanel.add(buildWestPanel(), BorderLayout.WEST); 
        buttonPanel.add(buildNumPanel(), BorderLayout.CENTER); 

        panel.add(buttonPanel, BorderLayout.CENTER); 
        con.add(panel); 

        /** 
        * De menubalk componenten realiseren en benoemen. 
        */ 
        optie1 = new MenuItem(" Copy "); 
        optie2 = new MenuItem(" Paste "); 
        optie3 = new MenuItem(" Quit "); 
        viewOptie1 = new MenuItem("Default"); 
        viewOptie2 = new MenuItem("Scientific"); 
        helpOptie = new MenuItem("Info"); 

        /** 
        * Toevoegen van edit/view/help componenten aan de menus. 
        */ 
        editDropDownMenu.add(optie1); 
        editDropDownMenu.add(optie2); 
        editDropDownMenu.addSeparator(); 
        editDropDownMenu.add(optie3); 
        viewDropDownMenu.add(viewOptie1); 
        viewDropDownMenu.add(viewOptie2); 
        helpDropDownMenu.add(helpOptie); 

        /** 
        * aan het menubalkje de edit/view/help dropdown opties toevoegen. 
        */ 
        menuBalk.add(editDropDownMenu); 
        menuBalk.add(viewDropDownMenu); 
        menuBalk.add(helpDropDownMenu); 


       /** 
       * Build the northPanel 
       * 
       * @return JPanel The created panel 
       */ 
       private JPanel buildNorthPanel() { 
        JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT)); 

        // We have a placeholder on the top right 
        JPanel placeHolder = new JPanel(); 
        placeHolder.setPreferredSize(new Dimension(BUTTON_HEIGHT, BUTTON_HEIGHT)); 
        placeHolder.setBorder(BorderFactory.createLoweredBevelBorder()); 
        p.add(placeHolder); 

        createNorthButton("Backspace", p).addActionListener(new BackspaceActionListener()); 
        createNorthButton("CE", p).addActionListener(new CEActionListener()); 
        createNorthButton("C", p).addActionListener(new CActionListener()); 

        return p; 
       } 

       /** 
       * Build the westPanel 
       * 
       * @return JPanel The created panel 
       */ 
       private JPanel buildWestPanel() { 
        JPanel p = new JPanel(new GridLayout(4, 1, 5, 5)); 
        p.setBorder(new EmptyBorder(0, 3, 3, 0)); 

        createWestButton("MC", p); 
        createWestButton("MR", p); 
        createWestButton("MS", p); 
        createWestButton("M+", p); 

        return p; 
       } 

       /** 
       * Build the numPanel 
       * 
       * @return JPanel The created panel 
       */ 
       private JPanel buildNumPanel() { 
        JPanel p = new JPanel(new GridLayout(4, 5, 5, 5)); 
        p.setBorder(new EmptyBorder(0, 0, 4, 4)); 

        createNumButton("7", p); 
        createNumButton("8", p); 
        createNumButton("9", p); 
        createNumButton("/", p); 
        createNumButton("sqrt", p); 

        createNumButton("4", p); 
        createNumButton("5", p); 
        createNumButton("6", p); 
        createNumButton("*", p); 
        createNumButton("%", p); 

        createNumButton("1", p); 
        createNumButton("2", p); 
        createNumButton("3", p); 
        createNumButton("-", p); 
        createNumButton("1/x", p); 

        createNumButton("0", p); 
        createNumButton("+/-", p); 
        createNumButton(",", p); 
        createNumButton("+", p); 
        createNumButton("=", p); 

        return p; 
       } 

       /** 
       * Calculate the result from a string containing a calculation 
       */ 
       public double calcResult(String text) { 
        // We use the build-in JavaScript engine to calculate the result 
        // this saves us a lot of weird conversions and complex calculations 
        ScriptEngineManager sem = new ScriptEngineManager(); 
        ScriptEngine engine = sem.getEngineByName("JavaScript"); 

        // Do some pre processing to allow javascript to do something with it 
        text = text.replace("sqrt(", "Math.sqrt("); 

        try { 
         return (double) engine.eval(text); 
        } catch (ScriptException e) { 
         JOptionPane.showMessageDialog(null, "Er was een probleem met het evalueren van uw input", "foutmelding", JOptionPane.ERROR_MESSAGE); 
        } 

        return 0.0; 
       } 

       /** 
       * This will run when the application is run from the jar file 
       * 
       * @param args Arguments 
       */ 
       public static void main(String[] args) { 
        Calculator app = new Calculator(); 
        app.go(); 
       } 

       /** 
       * Create a button 
       * 
       * @param String Contents 
       * @param JPanel The panel to add 
       * @return JButton The created button 
       */ 
       private JButton createButton(String contents, JPanel p) { 
        JButton b = new JButton(contents); 
        b.setMargin(new Insets(0,0,0,0)); 
        p.add(b); 

        return b; 
       } 

       /** 
       * Create a button for the NumPanel 
       * 
       * @param String Contents 
       * @param JPanel The panel to add 
       * @return JButton The created button 
       */ 
       private JButton createNumButton(String contents, JPanel p) { 
        JButton b = createButton(contents, p); 
        b.setPreferredSize(new Dimension(BUTTON_HEIGHT, BUTTON_HEIGHT)); 
        b.addActionListener(new NumButtonActionListener()); 

        return b; 
       } 

       /** 
       * Create a button for the WestPanel 
       * 
       * @param String Contents 
       * @param JPanel The panel to add 
       * @return JButton The created button 
       */ 
       private JButton createWestButton(String contents, JPanel p) { 
        JButton b = createButton(contents, p); 
        b.setPreferredSize(new Dimension(BUTTON_HEIGHT, BUTTON_HEIGHT)); 
        b.addActionListener(new MemoryActionListener()); 

        return b; 
       } 

       /** 
       * Create a button for the NorthPanel 
       * 
       * @param String Contents 
       * @param JPanel The panel to add 
       * @return JButton The created button 
       */ 
       private JButton createNorthButton(String contents, JPanel p) { 
        JButton b = createButton(contents, p); 
        b.setPreferredSize(new Dimension(100, BUTTON_HEIGHT)); 

        return b; 
       } 

       /** 
       * Check if string b is a number 
       * 
       * @param String The string to check 
       * @return boolean String is a number or not 
       */ 
       public boolean isNumber(String b) { 
        try { 
         Double.parseDouble(b); 
        } catch(NumberFormatException ex) { 
         return false; 
        } 

        return true; 
       } 

       /** 
       * This class handles the buttons in the 'numPanel' 
       */ 
       class NumButtonActionListener implements ActionListener { 
        /** 
        * Responds to a click on the button 
        * 
        * @param ActionEvent The event object 
        */ 
        public void actionPerformed(ActionEvent ev) { 
         JButton source = (JButton) ev.getSource(); 
         String sourceText = source.getText(); 
         String origText = calcField.getText(); 

         String textToAdd = ""; 

         // If the text equals the default text, clear it 
         if(origText.equals(DEFAULT_TEXT)) { 
          calcField.setText(""); 
         } 

         // If you just calculated something and wish to use the result 
         // we don't want to clear the text for you, the text should only 
         // be cleared when you enter a new number 
         if (fieldIsResult && isNumber(sourceText)) { 
          calcField.setText(""); 
          fieldIsResult = false; 
         } else { 
          fieldIsResult = false; 
         } 

         // Some buttons have special uses 
         if(sourceText.equals("=")) { // Calculate the result 
          calcField.setText(""+calcResult(calcField.getText())); 
          fieldIsResult = true; 
         } else if(sourceText.equals("sqrt")) { // Square root needs a '(' 
          textToAdd = "sqrt("; 
         } else if(sourceText.equals("+/-") && origText.length() > 0) { // Toggle negative/non-negative number 
          char firstChar = origText.charAt(0); 
          if(firstChar == '-') { 
           calcField.setText(origText.substring(1, origText.length())); 
          } else { 
           calcField.setText("-"+origText); 
          } 
         } else { // Just append the button text 
          textToAdd = sourceText; 
         } 

         if(! textToAdd.equals("")) { // If there is something that needs to be appended 
          calcField.setText(calcField.getText() + textToAdd); 
         } 
        } 
       } 

       /** 
       * This class handles the backspace button 
       */ 
       class BackspaceActionListener implements ActionListener { 
        /** 
        * Responds to a click on the button 
        * 
        * @param ActionEvent The event object 
        */ 
        public void actionPerformed(ActionEvent ev) { 
         String newText = calcField.getText(); 

         // If there are characters 
         if(newText.length() > 0) { 
          // Remove the last one 
          newText = newText.substring(0, newText.length() - 1); 
         } 

         calcField.setText(newText); 
        } 
       } 

       /** 
       * This class handles the C button 
       */ 
       class CActionListener implements ActionListener { 
        /** 
        * Responds to a click on the button 
        * 
        * @param ActionEvent The event object 
        */ 
        public void actionPerformed(ActionEvent ev) { 
         // C will simply clear the field 
         calcField.setText(""); 
        } 
       } 

       /** 
       * This class handles the CE button 
       */ 
       class CEActionListener implements ActionListener { 
        /** 
        * Responds to a click on the button 
        * 
        * @param ActionEvent The event object 
        */ 
        public void actionPerformed(ActionEvent ev) { 
         // C will simply clear the field 
         String newText = calcField.getText().replaceAll("[0-9]+$", ""); 
         calcField.setText(newText); 
        } 
       } 

       /** 
       * This class handles all the memory actions 
       */ 
       class MemoryActionListener implements ActionListener { 
        /** 
        * Respons to a click on the button 
        * 
        * @param ActionEvent The event object 
        */ 
        public void actionPerformed(ActionEvent ev) { 
         JButton source = (JButton) ev.getSource(); 
         String sourceText = source.getText(); 

         if(sourceText.equals("MC")) { 
          memory = 0.0; // Clear memory 
         } else if (sourceText.equals("MR")) { 
          calcField.setText(""+memory); 
          fieldIsResult = true; 
         } else if (sourceText.equals("MS") && fieldIsResult) { 
          memory = Double.parseDouble(calcField.getText()); 
         } else if (sourceText.equals("M+") && fieldIsResult) { 
          memory = calcResult(memory+"+"+calcField.getText()); 
         } 
        } 
       } 
      } 

這是怎麼了實例的類「NumButtonActionListener」的樣子,當我分開吧。

public class NumButtonActionListener extends Calculator implements ActionListener { 

       // boolean A flag whether the text in the antwoordCalculatieEntryfield is the result of a calculation 
       private boolean antwoordCalculatieEntryfield; 
       //JTextField The field in which the calculations are created 
       private JTextField entryField; 


       /** 
       * Responds to a click on the button 
       * 
       * @param ActionEvent The event object 
       */ 

//line 25 
       public void actionPerformed(ActionEvent ev) { 
        JButton source = (JButton) ev.getSource(); 
        String sourceText = source.getText(); 
//line 29 
        String origText = entryField.getText(); 

        String textToAdd = ""; 

        // If the text equals the default text, clear it 
        if(origText.equals("0.")) { 
         entryField.setText(""); 
        } 

        // If you just calculated something and wish to use the result 
        // we don't want to clear the text for you, the text should only 
        // be cleared when you enter a new number 
        if (antwoordCalculatieEntryfield && isNumber(sourceText)) { 
         entryField.setText(""); 
         antwoordCalculatieEntryfield = false; 
        } else { 
         antwoordCalculatieEntryfield = false; 
        } 

        // Some buttons have special uses 
        if(sourceText.equals("=")) { // Calculate the result 
         entryField.setText(""+calcResult(entryField.getText())); 
         antwoordCalculatieEntryfield = true; 
        } else if(sourceText.equals("sqrt")) { // Square root needs a '(' 
         textToAdd = "sqrt("; 
        } else if(sourceText.equals("+/-") && origText.length() > 0) { // Toggle negative/non-negative number 
         char firstChar = origText.charAt(0); 
         if(firstChar == '-') { 
          entryField.setText(origText.substring(1, origText.length())); 
         } else { 
          entryField.setText("-"+origText); 
         } 
        } else { // Just append the button text 
         textToAdd = sourceText; 
        } 

        if(! textToAdd.equals("")) { // If there is something that needs to be appended 
         entryField.setText(entryField.getText() + textToAdd); 
        } 

       } 

       /** 
       * Check if string b is a number 
       * 
       * @param b The string to check 
       * @return boolean String is a number or not 
       */ 
       public boolean isNumber(String b) { 
        try { 
         Double.parseDouble(b); 
        } catch(NumberFormatException ex) { 
         return false; 
        } 

        return true; 
       } 

       /** 
       * Calculate the result from a string containing a calculation 
       */ 
       public double calcResult(String text) { 
        // We use the build-in JavaScript engine to calculate the result 
        // this saves us a lot of weird conversions and complex calculations 
        ScriptEngineManager sem = new ScriptEngineManager(); 
        ScriptEngine engine = sem.getEngineByName("JavaScript"); 

        // Do some pre processing to allow javascript to do something with it 
        text = text.replace("sqrt(", "Math.sqrt("); 

        try { 
         return (double) engine.eval(text); 
        } catch (ScriptException e) { 
         JOptionPane.showMessageDialog(null, "Er was een probleem met het evalueren van uw input", "foutmelding", JOptionPane.ERROR_MESSAGE); 
        } 

        return 0.0; 
       } 


       } 
+0

對於錯誤信息,可能還有比您給我們更多的東西嗎? – pamphlet 2014-09-05 14:39:47

+0

真的,我想,這是最重要的一個..我現在要添加完整列表。 – 2014-09-05 14:42:47

+0

您可以將NumButtonActionListener從Calculator類中分離出來後發佈,並將第25行的註釋放在該錯誤的位置,以便我們可以看到該行? – 2014-09-05 15:08:03

回答

1

你的產業的理解是完全錯誤的

NumButtonActionListener extends Calculator 

請看下面的例子:

public class Foo { 
    FooBoo foofoo; 

    public Foo() { 
     foofoo = new FooBoo(); 
     Bar bar = new Bar(); 
    } 
} 

public class Bar extends Foo { 
    public Bar() { 
     someMethod(); 
    } 
    void someMethod() { 
     foofoo.method(); 
    } 
} 

當你創建一個實例new Bar(),這將導致一個NullPointerException因爲FooBooFoo類是不是相同FooBooBar類。他們絕不是同一個參考。 Bar實例中的FooBoo從未初始化。

你有太多的代碼要通過,所以我不會嘗試修復你的代碼。但我會告訴你如何去解決這個問題。爲了Bar使用相同的FooBoo對象作爲Foo中的對象,它需要引用它。一種方法是簡單地將它傳遞給構造函數。像

public class Foo { 
    FooBoo foofoo; 

    public Foo() { 
     foofoo = new FooBoo(); 
     Bar bar = new Bar(foofoo); 
    } 
} 

public class Bar { 
    FooBoo foo; 

    public Bar(FooBoo foo) { 
     this.foo = foo; 
     someMethod(); 
    } 
    void someMethod() { 
     foo.method(); 
    } 
} 

東西,所以你通過FooFooBooBar的參考。那麼它就是相同的引用FooBoo對象。請注意,我沒有製作Bar延伸Foo。這不是繼承的正確使用。

+0

wauw,有道理。有趣的是,我知道這一點。但不知怎的,它並沒有到我這裏來實現它到我的計算器報價。因爲一個班。它確實有用。有很多東西要學。謝謝;) – 2014-09-05 16:03:45

+2

@M D你應該接受peeskillet的答案,如果你發現它有幫助 - 它花費在一起的努力。 – Greycon 2014-09-05 16:18:10