为什么我的方法不是在我的其他类中添加值? (包括sscce)

时间:2013-12-13 21:48:10

标签: java swing awt

所以我对java很新。

此程序现在正在运行。这是一个食品订购系统。它使用每个标签都带有网格。每个标签都有自己的价格。

我的问题是当我运行并编译程序时,它会运行,但价格不会累加。 基本上,在下面列出的GUI类中,有一种方法可以从每个选项卡中获取价格并将它们相加....除非它没有这样做。确实出现了,但“0.00美元”并没有改变。

就像我说它编译一样,然而,当我按下按钮时,我可以看到编译器出现了这个错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException

这是主要课程:

import javax.swing.JFrame;

public class Pizzamain
{


     public static void main (String[] args)
   {
      JFrame frame = new JFrame ("Pizza Mutt Ordering Service");
      frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new PizzaMuttPanel());
      frame.pack();
      frame.setVisible(true);


    }

}

此类包含所有GUI。它还会在每个标签中累计价格。我注释掉了其他标签。

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.text.NumberFormat;

public class PizzaMuttPanel extends JPanel
{
    private JLabel totalLabel;
   private double total;




    public PizzaMuttPanel()
   {
      setLayout (new BorderLayout());

      JLabel name = new JLabel("Pizza Mutt Ordering Service WOOF! WOOF!");
      JPanel namePanel = new JPanel();
      namePanel.add(name);
      add(namePanel, BorderLayout.NORTH);

      JTabbedPane mainTabPane = new JTabbedPane();
      mainTabPane.add("Pizza", new PizzaPanel());
     // mainTabPane.add("Drinks", new DrinksPanel());
     // mainTabPane.add("Specials", new SpecialsPanel());
      add(mainTabPane, BorderLayout.CENTER);

      total = 0.0;
      JPanel totalPanel = new JPanel();
      totalPanel.add (new JLabel("Your total is:"));
      totalLabel = new JLabel("$0.00");
      totalPanel.add(totalLabel);
      add(totalPanel, BorderLayout.SOUTH);

      }



   public void addTotal (double intake)
   {
      total += intake;
      NumberFormat dollars = NumberFormat.getCurrencyInstance();
      totalLabel.setText(dollars.format(total));
   }
}

这是其中一个标签的示例。顺便说一句,所有标签都遵循这个逻辑。正如您所看到的,在操作部分中,每次按下按钮时都会添加价格,然后将数据中继到GUI类。

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


public class PizzaPanel extends JPanel
{
private double price;
private final JButton pl;
private final JButton ps;
private final JButton cl;
private final JButton cs;
private final JButton vl;
private final JButton vs;
private PizzaMuttPanel mainPanel;


   public PizzaPanel()
   {
      setLayout (new GridLayout (2, 3));

      setBackground (Color.red);

      pl = new JButton ("Large Pepperoni: $7");
      ps = new JButton ("Small Pepperoni: $4");
      cl = new JButton ("Large Cheese: $6.50");
      cs = new JButton ("Small Cheese: $3.50");
      vl = new JButton ("Large Vegetable: $7");
      vs = new JButton ("Small Vegetable: $4");

      add (pl);
      add (ps);
      add (cl);
      add (cs);
      add (vl);
      add (vs);



      pl.addActionListener(new ButtonListener());
      ps.addActionListener(new ButtonListener());
      cl.addActionListener(new ButtonListener());
      cs.addActionListener(new ButtonListener());
      vl.addActionListener(new ButtonListener());
      vs.addActionListener(new ButtonListener());



   }  

          //Here we listen for button presses

         private class ButtonListener implements ActionListener
   {
                   public void actionPerformed (ActionEvent e)
               {
                 if (e.getSource().equals(pl)) 

                     {

                       price+=7;


                      }

                if(e.getSource().equals(ps)) 

                      {

                         price+=4;


                       } 

                  if (e.getSource().equals(cl)) 
                        {

                         price+=6.5;


                        }

                   if (e.getSource().equals(cs)) 
                        {
                         price+=3.5;


                        } 
                    if (e.getSource().equals(vl)) 
                        {

                         price+=7;


                        }

                   if (e.getSource().equals(vs)) 
                        {

                         price+=4;


                        }
     //This adds all the prices together.                    
                mainPanel.addTotal(price);

        }}}

2 个答案:

答案 0 :(得分:3)

一种方式,也许对你来说过度杀戮,但这是一种非常有用的知识和使用方法,就是让保存JPanel所显示信息的对象成为一个“绑定属性”,允许其他类能够倾听并回应其状态的变化。

具体做法是:

  • 为您的班级提供感兴趣的信息SwingPropertyChangeSupport字段。
  • 如果您的类扩展了JComponent或JPanel(或任何派生自JComponent的类),那么它已经有了其中一个。
  • 为您的班级提供私人count int字段
  • 为此字段提供公共getter和setter方法。
  • 在setter字段中,使用更新的旧值调用SwingPropertyChangeSupport的firePropertyChange(String propertyName, int oldValue, int newValue)方法。
  • 从不直接更改绑定属性,但只能通过其setter方法。
  • 任何想要侦听更改的类都会向此类添加PropertyChangeListener。

如果您需要更具体的示例,请考虑创建并发布sscce,我可以向您展示如何修改它以使其生效。


修改
您当前的代码存在引用问题 - 您需要子面板具有对主面板的有效引用,您应该通过传入引用来解决此问题。

e.g。

private MainPanel mainPanel;

public SubPanelA(MainPanel mainPanel) { 
   this.mainPanel = mainPanel; 

然后填写标签时:

  mainTabPane.add("A", new SubPanelA(this)); 
  mainTabPane.add("B", new SubPanelB(this)); 
  mainTabPane.add("C", new SubPanelC(this));

这样,选项卡窗格类可以在对主显示的主类的有效引用上调用主类中的方法。


编辑2
你说:

  

我有点困惑。但我有参考,对吧?在buttonlistener类中,首先是我私有的PizzaMuttPanel mainPanel;在顶部,然后我将其引用为mainPanel.addTotal(price);. Addtotal在主GUI类中,并保存价格。价格是特定标签类中按钮按下的价格。你是说我应该将后者改为:mainTabPane.add(“A”,新的SubPanelA(this));

要点:

  • 这:PizzaMuttPanel mainPanel;不是引用,而只是引用变量的声明。在声明之后,它引用null,直到你给它一个有效的引用。
  • 你陈述"and then I referenced it as mainPanel.addTotal(price);",???这没有任何参考,看起来我只会抛出一个NPE。要为变量提供引用,您必须指定对它的引用,这意味着您需要一些以mainPanel = something goes here开头的语句。

答案 1 :(得分:2)

所以我的理解是你在jtabbedpane上有三个不同的标签。每个选项卡都是扩展JPanel的类。因此,您希望为每个选项卡添加一个actionlistener,您只需在每个面板上实现Actionlistener接口,或者在每个按钮上实现。

class tab extends JPanel implements Actionlistener

或者如果你想要一个特定的actionlistener

button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
                    //Action here for the button
        }
});

然后,您希望从每个标签中获取信息,以便将变量价格设为公开或私有。但要访问私有变量,你必须制作getter。

public int price;

或私人版本。

private int price;
public int getPrice(){ return price; }

最后一种方式是首选方式,因为您无法更改包含该变量的类之外的价格值。

最后你想从这三个标签中获取信息,你可以这样做。

public void prices()
{
    Tab1 tab1 = new Tab1();
    Tab2 tab2 = new Tab2();
    Tab3 tab3 = new Tab3();

    System.out.println("tab1: " + tab1.price + " tab2: " + tab2.price + " tab3:    " + tab3.price);
    // or if you use getters
    System.out.println("tab1: " + tab1.getPrice() + " tab2: " + tab2.getPrice() + " tab3: " + tab3.getPrice());
}

那你在哪里宣布它?

class tab extends JPanel implements ActionListener
{
   /*
    * Declare variables here
    */
    private int price;
    private JLabel label;

   /*
    * Methods here
    */
}

修改

问题是你要检查按钮是否被文本点击而不是变量。另一件事是你每次都给出一个按钮监听器的新实例。我们只是在PizzaPanel类上实现接口ActionListener,而不是创建一个名为ButtonListener的新类。

public class PizzaPanel extends JPanel implements ActionListener{

private JButton b1 = null;
private JButton b2 = null;

private int Price;

public int getPrice() {
    return Price;
}

public PizzaPanel() {
    b1 = new JButton("B1");
    b2 = new JButton("B2");

    b1.addActionListener(this);
    b2.addActionListener(this);

    add(b1);
    add(b2);
}

@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource().equals(b1)){
        Price++;
        System.out.println("Button 1 clicked");
    }
    if(e.getSource().equals(b2))
    {
        Price--;
        System.out.println("Button 2 clicked");
    }
}
}