簡體   English   中英

如何使用另一個類的按鈕更改 JLabel?

[英]How to change a JLabel with a button from another class?

我有兩個類和一個文本文件數據庫,第一個類中的JLabel ,我們稱之為class1自動將其設置為數據庫中的數字。 現在,在class2我有這個小JFrame和一個文本字段,當然還有一個按鈕,我放在文本字段中的值會覆蓋數據庫中的值,但問題就在這里。 第一個類中的標簽在運行時不會更新,但是如果我重新啟動它,它將顯示我想要的值。

如何在程序運行時更新它? 我試圖更改在另一個類中執行的buttonActionperformed中的標簽,但它每次都給我一個NullPointException

我該如何解決?

主要類(只是 JFRAME)

package BankrollG;

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

public class 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();
    }
}

然后你得到了包含組件的類:

private 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 方法將不起作用,因為值在那里,但它不會更新 JLabel。

我希望這能讓我更容易理解我的問題。 它有更多的代碼,與此無關,我希望我至少簡化了一些。

您的問題是 Java 編程中一個基本問題的具體示例——如何在類之間傳輸信息。 有幾種方法可以做到這一點,最優雅的方法之一是使用一個“模型”類來保存程序的邏輯代碼和關鍵數據,讓一個類通過更改它保存的文本字符串來更改模型的狀態。 然后使用偵聽器或觀察者模式,讓模型通知另一個類它已被更改,以便另一個類可以從模型中提取新信息,即它的新字符串。 雖然這可能是最好的解決方案,但它可能有點矯枉過正,並且可能高於您當前的編碼水平,因此對於您來說,我不會推薦這個。

相反,我將推薦一種更簡單的不太優雅的解決方案,您可以讓一個類調用另一個類的 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方法,它允許其他類設置ButtonTextFieldClass用適當的LabelClass實例。

例如,

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 中,它也可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM