2014-12-22 48 views
0

我有兩個類和一個文本文件數據庫,第一類的JLabel,我們稱之爲class1自動將它自己設置爲數據庫中的數字。現在,在class2中,我有這個小小的JFrame和一個文本字段,當然還有一個按鈕,我放入文本字​​段的值會覆蓋數據庫中的值,但問題來了。第一類中的標籤在運行時不會更新,但如果我重新啓動它,它會顯示我想要的值。如何使用另一個類的按鈕更改JLabel?

如何在程序運行時更新它? 我試圖改變其他班級的buttonActionperformed中的標籤,但每次都會給我一個NullPointException

我該如何解決這個問題?

主類(JUST 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

公共BGbody(){

panel.setLayout(null); 
    windowComponents(); 


} 

公共無效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功能

私人無效AddcurrencyActionPerformed(java.awt.event.ActionEvent中EVT)創建JFrame類{

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」因爲我t只是返回nullpointsexceptions。數據在那裏,因爲jlabel從數據庫中讀取數據,但是當按鈕類發生變化時它不會更新。所以一個getter setter方法不會工作,因爲值是那裏,但它不會更新JLabel。

我希望這可以讓我更容易理解我的問題。 它是更多的代碼,這不需要做到這一點,我希望我簡化了至少一些。

感謝

+1

'「如何在程序運行時更新它?我試着改變buttonAction在其他類中的JLabel,但它每次都會給我一個nullpointexception。」 - 那麼你必須調試你的NullPointerException(或NPE)。你應該仔細閱讀你的異常的堆棧跟蹤來找到有故障的代碼行,引發異常的代碼行,然後**仔細檢查那行代碼**,找出哪個變量爲空,然後追溯到代碼中以查看爲什麼。你會一次又一次遇到這些,相信我。 –

+0

如果您需要我們的幫助,代碼會幫助很多**,最好是[最小示例程序](http://stackoverflow.com/help/mcve),這是一個小但完整的程序,只有必要的代碼展示你的問題,我們可以複製,粘貼,編譯和運行而不用修改。 –

+0

我做了class1 Class1 c1的變量;我試着改變這一行:c1.labelname =「thevalue」; <---剛進入數據庫的值,但沒有任何事情發生,除了我得到一個nullpointexception ..:/ – Alexander

回答

2

你提的問題是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方法,允許其他類使用正確的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設爲私人,併爲該課程提供了公開設置方法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中而另一個JPanel在JDialog中,它也可以工作。

+0

謝謝你!但問題在於它沒有獲取它不會更新的信息,我真正需要做的就是通過點擊我其他課程中的按鈕來更新我的方法。我有很多代碼幾乎添加了1000行代碼,所以它很難如此簡化:( – Alexander

+0

我試過while循環以立即保持它更新,但然後我的窗口甚至不會顯示,因爲它更新了很多次.. – Alexander

+0

@Alexander :你的第一個任務是調試你的問題,找出你當前的代碼拋出一個NPE的原因。請閱讀我的關於這個問題的原始問題的鏈接。是的,一個while循環是一個壞主意,因爲它會跺腳Swing事件線程會凍結你的GUI,但是你不需要輪詢數據(你在上面的註釋中嘗試過的解決方案),而是希望得到更改的通知 –

相關問題