我有两个类和一个文本文件数据库,第一个类中的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。
我希望这能让我更容易理解我的问题。 这是更多的代码,与此无关,我希望我简化它至少一些。
谢谢
答案 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);
}
}
然后要设置所有内容,在另一个类中,我将创建LabelClass
和ButtonTextFieldClass
的实例,然后通过调用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中,它也可以正常工作。