如何使用另一个类的按钮更改JLabel?

时间:2014-12-22 00:52:11

标签: java swing nullpointerexception

我有两个类和一个文本文件数据库,第一个类中的JLabel,我们称之为class1自动将它自己设置为数据库中的数字。现在,在class2我有这个小JFrame和一个文本字段,当然还有一个按钮,我放在文本字段中的值会覆盖数据库中的值,但这就是问题所在。第一个类中的标签在运行时不会更新,但是如果我重新启动它会显示我想要的值。

如何在程序运行时更新它? 我尝试更改其他课程buttonActionperformed中的标签,但每次都给我一个NullPointException

我该如何解决这个问题?

主要类别(只是JFRAME)

包BankrollG;

import java.awt.Graphics; import javax.swing.JFrame;

公共班级BGbrain {

BGbody body = new BGbody();
JFrame Frame = new JFrame();

public BGbrain(){

    Frame.setSize(body.width, body.height);
    Frame.setTitle(body.title);
    Frame.setResizable(false);
    Frame.setDefaultCloseOperation(Frame.EXIT_ON_CLOSE);
    Frame.add(body.panel);
    Frame.setLocationRelativeTo(null);
    Frame.setFocusable(true);

    Frame.setVisible(true);


}



public static void main(String[] args ){

    new BGbrain();

}

}

然后你得到了包含组件的类:

私人JLabel bankroll_label

public BGbody(){

    panel.setLayout(null);
    windowComponents();


}

public void windowComponents(){

    // Bankroll database access
        try{

        FileReader fr = new FileReader("Bankroll.txt");
        BufferedReader br = new BufferedReader(fr);
        set_bankroll = br.readLine();



        }catch(IOException e)
        {
            System.out.println("FEL MED LÄSNING AV DATABAS /// BGBODY");
        }

}

然后你得到了我用netbeans函数创建的JFrame类

private void AddcurrencyActionPerformed(java.awt.event.ActionEvent evt){

    String CBR = txt_bankroll.getText();

  try{
  FileWriter fw = new FileWriter("Bankroll.txt");
  PrintWriter pw = new PrintWriter(fw);

  pw.println(CBR);
  pw.close();





  }catch(IOException e){

      System.out.println("FEL MED INSKRIVNINGEN I DATABASEN");

  }





}         

现在,一切都按计划进行,但我无法从按钮类更新我的JLabel“bankroll_label”,因为它只返回nullpointsexceptions。数据存在,因为jlabel从数据库读取,但是当从按钮类进行更改时它不会更新。因此,getter setter方法不会起作用,因为值为IS但它不会更新JLabel。

我希望这能让我更容易理解我的问题。 这是更多的代码,与此无关,我希望我简化它至少一些。

谢谢

1 个答案:

答案 0 :(得分:2)

您的问题是Java编程中基本问题的一个具体示例 - 如何在类之间传递信息。有几种方法可以做到这一点,其中一个最优雅的方法是使用一个“模型”类来保存程序的逻辑代码和关键数据,让一个类通过更改它所拥有的文本字符串来改变模型的状态。然后使用侦听器或观察者模式,让模型通知另一个类它已被更改,以便另一个类可以从模型中提取新信息,即新的String。虽然这可能是最好的解决方案,但它可能有点过分,可能高于你目前的编码水平,所以对你来说,我不打算推​​荐这个。

相反,我将推荐一个更简单的不太优雅的解决方案,你可以让一个类调用另一个类的setter方法来新的String推入其中。

我们作为志愿者回答者的一个问题是,您的问题很难回答,因为它缺少关键代码,因此我们很难猜测您的代码为什么行为不端,为什么具体你是尝试运行它时遇到NullPointerException(或NPE)。所以我所能做的只是猜测,但我猜我会尝试。

为了简单起见,让我们调用一个类,即持有JLabel的类,LabelClass和另一个类ButtonTextFieldClass

一个可能的原因是你有一个NullPointerException是因为你的ButtonTextFieldClass可能有一个LabelClass变量,但从未初始化变量,如下所示:

// this guy is null because it is never initialized
private LabelClass labelClass; 

一个简单的解决方案可能是尝试初始化它:

private LabelClass labelClass = new LabelClass();

但这不起作用,因为虽然它确实创建并分配了LabelClass实例,但它可能不是在运行的GUI中可视化的LabelClass实例。

更好的解决方案是为ButtonTextFieldClass提供一个setter方法,允许其他类使用正确的LabelClass实例设置ButtonTextFieldClass

如,

public void setLabelClass(LabelClass labelClass) {
   this.labelClass = labelClass;
}

这样设置两个类的代码可以将可视化的LabelClass传递给第一个类,并且可以在其上调用方法。

LabelClass的一个简单示例可能如下所示:

class LabelClass extends JPanel {
   private JLabel label = new JLabel("");

   public LabelClass() {
      setBorder(BorderFactory.createTitledBorder("Label Panel"));
      add(label);
   }

   public void setLabelText(String text) {
      label.setText(text);
   }
}

我扩展了JPanel,因为这样我可以自由地将它放入JFrame或JDialog或其他JPanel中。请注意,我已将JLabel设为私有,并为该类提供了一个公共setter方法setLabelText(String text),该方法允许外部类设置JLabel的文本。

ButtonTextFieldClass看起来像:

class ButtonTextFieldClass extends JPanel {
   private JTextField textField = new JTextField(10);
   private JButton button = new JButton(new ButtonAction("Send Text"));
   private LabelClass labelClass;

   public ButtonTextFieldClass() {
      setBorder(BorderFactory.createTitledBorder("Button TextField Panel"));
      add(textField);
      add(button);
   }

   // here we allow other classes to set instances of our LabelClass  
   public void setLabelClass(LabelClass labelClass) {
      this.labelClass = labelClass;
   }

   // ....

我还给了一个AbstractAction按钮来代替ActionListener,因为它就像是类固醇上的超级ActionListener。在其中,我将从JTextField获取文本,然后调用LabelClass的setter方法(如果变量不为null)来设置标签的文本:

  public void actionPerformed(ActionEvent e) {
     String text = textField.getText(); 
     if (labelClass != null) {
        labelClass.setLabelText(text);
     }
  }

然后要设置所有内容,在另一个类中,我将创建LabelClassButtonTextFieldClass的实例,然后通过调用setter方法“将它们连接起来”:

  LabelClass labelClass = new LabelClass();
  ButtonTextFieldClass buttonTextFieldClass = new ButtonTextFieldClass();
  buttonTextFieldClass.setLabelClass(labelClass); // set our reference

整件事情可能如此:

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

public class TransferData {

   private static void createAndShowGui() {
      LabelClass labelClass = new LabelClass();
      ButtonTextFieldClass buttonTextFieldClass = new ButtonTextFieldClass();
      buttonTextFieldClass.setLabelClass(labelClass); // set our reference

      JPanel mainPanel = new JPanel(new GridLayout(0, 1));
      mainPanel.add(buttonTextFieldClass);
      mainPanel.add(labelClass);

      JFrame frame = new JFrame("TransferData");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

class LabelClass extends JPanel {
   private JLabel label = new JLabel("");

   public LabelClass() {
      setBorder(BorderFactory.createTitledBorder("Label Panel"));
      add(label);
   }

   public void setLabelText(String text) {
      label.setText(text);
   }
}

class ButtonTextFieldClass extends JPanel {
   private JTextField textField = new JTextField(10);
   private JButton button = new JButton(new ButtonAction("Send Text"));

   // one possible solution -- give this class a variable 
   // of the LabelClass -- but don't initialize the variable 
   // here, but rather do it in a setter
   private LabelClass labelClass;

   public ButtonTextFieldClass() {
      setBorder(BorderFactory.createTitledBorder("Button TextField Panel"));
      add(textField);
      add(button);
   }

   // here we allow other classes to set instances of our LabelClass  
   public void setLabelClass(LabelClass labelClass) {
      this.labelClass = labelClass;
   }

   // an AbstractAction is like a "super" ActionListener
   private class ButtonAction extends AbstractAction {
      public ButtonAction(String name) {
         super(name); // set the button's text and actionCommand
         int mnemonic = (int) name.charAt(0); // get first char
         putValue(MNEMONIC_KEY, mnemonic); // set mnemonic
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         String text = textField.getText(); 
         if (labelClass != null) {
            labelClass.setLabelText(text);
         }
      }
   }
}

为简单起见,我在同一个GUI中显示了两个JPanel,但如果一个JPanel在一个JFrame中,另一个在JDialog中,它也可以正常工作。