【问题标题】:Java Calculator Operator Errors [closed]Java计算器运算符错误[关闭]
【发布时间】:2015-09-28 11:23:31
【问题描述】:

我用 Java swing 库构建了一个计算器。除了 actionEvent 循环中的乘法和除法运算符外,其他一切都有效。所有其他 Operator 都可以正常工作。

这是发生错误: 我已经在这部分代码上尝试了一个 try 语句

计算器:

计算器乘法错误:

  1. 首先输入数字

  2. 然后你按下操作符,这应该是清除文本字段 - 这一步发生错误

  3. 然后你输入第二个数字

  4. 然后按=键输出答案

错误图片:

if(e.equals("*"))
{
        fnum = txt.getText();
        logic.setTotal(fnum);
        op = "*";
        txt.setText(""); // error occurs here, textfield isn't cleared
        JOptionPane.showMessageDialog(null, fnum); //messagebox to see if fnum contains the string from the textfield
}
if(e.equals("/"))
{
        fnum = txt.getText();
        op = "/";
        txt.setText("");
}

ActionEvent 循环/函数:

public void actionPerformed(ActionEvent ea)
{
    else if(op.equals("*"))
    {
        logic.setTotal(fnum);
        logic.multiplication(snum);
        total1 = logic.total;
    }
    else if(op.equals("/"))
    {
        logic.setTotal(fnum);
        logic.divide(snum);
        total1 = logic.total;
    }
    txt.setText(""+total1);
}

逻辑是内部类

内部类:

public class Inner extends Calculators{
    public double total;
    public Inner()
    {
        total = 0;
    }
    public void setTotal(String n)
    {
        total = convertToNumber(n); 
    }
    public void divide(String n)
    {
        total /= convertToNumber(n);
    }
    public void multiplication(String n)
    {
        total *=convertToNumber(n);
    }
}

如果您感到困惑,请索取更多代码,因为我无法包含所有代码。

Code if you want to try it out yourself

【问题讨论】:

  • 这让我很担心:public class Inner extends Calculators{。为什么内部扩展计算器?这表明滥用继承权。否则,如果没有minimal example program,将很难回答您的问题。
  • 内部类使用计算器方法和变量,因为它是计算器的“子类”。我无法添加所有代码,因为它非常广泛。
  • 您看到了什么特别的错误?发生错误时的类代码会很有帮助。
  • "Inner class uses Calculator methods and variable. I need it to use the logic methods" -- 这不是继承的用途。如果它是一个内部类,那么它已经可以访问其外部类的变量和方法。我担心这里的设计问题。另一个问题,你在这里陈述:"ActionEvent Loop:"——但没有显示循环。也许你贴错了标签。
  • 您最好按照上面的 Hovercraft 要求发布 MCVE。真的很难理解错误是什么,发生在哪里,在什么情况下发生,以及为什么我们不能自己运行和观察。而且您只给出了可能相关或不相关的程序的一小部分。

标签: java swing


【解决方案1】:

你最初是这样创建按钮的:

    ...
    JButton plus = new JButton("+");
    JButton multiplication = new JButton("*");
    JButton divide = new JButton("/");
    JButton minus = new JButton("-");
    ...

然后添加this 作为动作监听器。但是有些行不见了:

    ...
    plus.addActionListener(this);
    // missing: multiplication.addActionListener(this);
    // missing: divide.addActionListener(this);
    minus.addActionListener(this);
    ...

我是如何发现这个错误的:

  1. 已下载代码、编译等
  2. 运行代码,尝试加法、乘法等(检查应用程序的行为)。这是一种黑盒测试
  3. 通过分析代码寻找加法和乘法之间的差异。这与白盒测试有关。
  4. 我看到应该调用JOptionPane.showMessageDialog(null, fnum); - 但尚未调用。所以我在断点(在eclipse中)调试
  5. 当我意识到我没有调用 actionPerformed 方法时,我搜索了注册 ActionListener 的代码行。

除此之外:我强烈建议重构您的代码。您可以从重新考虑代码结构中受益。您将获得更好的可读性,代码将更易于维护,新功能可以更快地实现。

我建议:

  • 降低字段的可见性。将您的字段设为private,以便您可以轻松找到对它们的所有引用。
  • 避免重复(称为不要重复自己技巧)。例如:不要为每个按钮调用addActionListener,而是创建一个按钮集合(即ArrayList<JButton>,并使用for 循环为每个按钮调用addActionListener
  • 还可以通过定义更多但更短的方法来避免重复的代码片段
  • 考虑删除您的类 Calculators 并将该代码直接放入 Inner 的方法中。
  • Inner 找到一个更有意义的名称。也许IntermediateResult 或类似的。
  • 为每个按钮创建一个单独的ActionListener 实例。这会消耗一点性能(人类不会注意到),但会避免长 if-chains
  • 将您的代码发布到 代码审查(在 StackExchange 网络中)以获得更多帮助和新想法

【讨论】:

  • 感谢您的帮助,感谢您的帮助。很好的答案!
【解决方案2】:

只是一个附带建议,与您的主要问题无关,这就是为什么我将其发布为社区 Wiki 而不是作为答案:不惜一切代价避免使用空布局。当然,虽然null 布局和setBounds(...) 对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但创建的 Swing GUI 越多,使用它们时遇到的困难就越严重。当 GUI 调整大小时,它们不会调整您的组件大小,它们是增强或维护的皇家女巫,放置在滚动窗格中时它们完全失败,在与原始不同的所有平台或屏幕分辨率上查看时它们看起来很糟糕.

例如,如果您使用布局的智能组合,您的 GUI 将能够自行组装,并且更加灵活,如果您决定更改按钮的位置或添加新按钮.例如:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;

public class Calc2 extends JPanel {
   private static final String[][] INITIAL_BTNS = {
      {"1", "2", "3", "+"},
      {"4", "5", "6", "-"},
      {"7", "8", "9", "*"},
      {"C", "0", ".", "/"},
      {"1/x", "\u221A", "Ln", "="}
   };
   private static final String[][] EXTRA_BTNS = {
      {"sin", "cos", "tan"},
      {"csc", "sec", "cot"}
   };
   private static final int GAP = 5;

   private JTextField displayField = new JTextField(10);

   public Calc2() {
      int rows = INITIAL_BTNS.length;
      int cols = INITIAL_BTNS[0].length;
      JPanel initialBtnPanel = new JPanel(new GridLayout(rows, cols, GAP, GAP));
      rows = EXTRA_BTNS.length;
      cols = EXTRA_BTNS[0].length;
      JPanel extraBtnPanel = new JPanel(new GridLayout(rows, cols, GAP, GAP));

      JPanel combinedBtnPanel = new JPanel();
      combinedBtnPanel.setLayout(new BoxLayout(combinedBtnPanel, BoxLayout.PAGE_AXIS));
      combinedBtnPanel.add(initialBtnPanel);
      combinedBtnPanel.add(Box.createVerticalStrut(GAP));
      combinedBtnPanel.add(extraBtnPanel);

      for (int r = 0; r < INITIAL_BTNS.length; r++) {
         for (int c = 0; c < INITIAL_BTNS[r].length; c++) {
            JButton button = new JButton(INITIAL_BTNS[r][c]);
            initialBtnPanel.add(button);
            // add action here
         }
      }

      for (int r = 0; r < EXTRA_BTNS.length; r++) {
         for (int c = 0; c < EXTRA_BTNS[r].length; c++) {
            JButton button = new JButton(EXTRA_BTNS[r][c]);
            extraBtnPanel.add(button);
            // add action here
         }
      }

      setLayout(new BorderLayout(GAP, GAP));
      setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));

      add(displayField, BorderLayout.PAGE_START);
      add(combinedBtnPanel, BorderLayout.CENTER);
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Calculator");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new Calc2());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

显示为:

如果稍后您决定在额外按钮部分的顶部添加 3 个按钮,您需要对我的代码做的就是添加一行代码(不计算所需的逻辑代码更改,这将是相同的为你和我的),并改变这个:

   private static final String[][] EXTRA_BTNS = {
      {"sin", "cos", "tan"},
      {"csc", "sec", "cot"}
   };

到这里:

   private static final String[][] EXTRA_BTNS = {
      {"foo", "bar", "baz"},
      {"sin", "cos", "tan"},
      {"csc", "sec", "cot"}
   };

无需手动更改所有其他按钮的位置或手动重新调整 JFrame 的大小,因为布局管理器会为您处理这些,并且 GUI 将显示为:

【讨论】:

  • 我认为我们的答案完美互补。这是定义和布局按钮的好方法!
  • 您如何建议为您的示例代码添加 ActionListener?
  • @slartidan:我可以创建3个或更多AbstractAction类,一个用于数字和.按钮,一个用于基本操作按钮,一个用于复杂操作按钮。我会使用 Map 将 String 与 Action 相关联,然后在 for 循环中,使用 Map 为按钮获取适当的 Action。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多