2012-09-13 51 views
5

我在同一個包中有兩個類。我已經在一個類中聲明瞭static variable,並且想要在另一個類中訪問該變量。從另一個類訪問靜態變量

這裏是我的代碼中,我已宣佈靜態變量

public class wampusGUI extends javax.swing.JFrame { 

    static String userCommand; 

    public wampusGUI() { 
     initComponents(); 
    } 

    public void setTextArea(String text) { 
     displayTextArea.append(text); 
    } 

    private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) { 
     userCommand = commandText.getText(); 
    } 

    public static void main(String args[]) { 
     /* Create and display the form */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       wampusGUI w = new wampusGUI(); 
       w.setVisible(true); 
       Game g = new Game(w); 
       g.play(); 
      } 
     }); 
    } 
} 

這裏是我想訪問變量

public class Game { 

    private wampusGUI gui; 

    public Game(wampusGUI w) { 
     world = new World(); 
     world.start(); 
     gui = w; 
    } 

    public void play() { 
     gui.setTextArea(welcome()); 
     gui.setTextArea(describe()); 
     for (;;) { 
      String s = userCommand; // here value should come should 
      System.out.println(userCommand); 
      Command c = Command.create(s); 
      String r = c.perform(world); 
      // is game over? 
      if (r == null) { 
       break; 
      } 
      System.out.println(r); 
     } 
     System.out.println("Game over"); 
    } 
} 

但是代碼,我可以先通過變量類作爲參數。但問題是,當我將運行程序的價值是空的第一次,我不想要的。我想當我在textfield輸入值,那麼它應該去另一個類。

謝謝。

+7

你是什麼意思的「價值是空的第一次」?基本上你應該改變你的設計 - 擁有一個全局變量真的不是一個好的解決方案。 –

+1

我同意@jon。在用戶有機會改變它之前,您的字符串將沒有體面的價值。此外,您的永久for循環不是Swing應用程序的良好設計。我在想,如果你真的想用一個監聽器來監聽用戶改變一個JTextField的狀態,然後對此進行操作。也許你也想看看使用Swing Timer,但很難知道,直到我們知道更多關於你的程序和它應該做什麼。 –

+0

請告訴我們:你想用這個代碼做什麼? –

回答

2

我建議你使用一種或另一種排列的偵聽器來允許Game對象偵聽和響應GUI對象狀態的變化。有幾種方法可以做到這一點,但我發現最優雅和最實用的方法之一就是使用Swing自己的先天PropertyChangeSupport來允許您使用PropertyChangeListeners。所有Swing組件都將允許您爲其添加PropertyChangeListener。所以,我建議你這樣做,你有遊戲添加一個到您的WampusGUI類(這應該是大寫)對象,像這樣:

public Game(WampusGUI w) { 
    gui = w; 

    gui.addPropertyChangeListener(new PropertyChangeListener() { 
    // .... 
    } 

這將使遊戲監聽在GUI中的狀態變化。

然後你會想讓gui的userCommand String成爲一個「綁定屬性」,這意味着給它一個setter方法,它將觸發屬性更改支持,通知所有的監聽器進行更改。我會做這個,像這樣:

private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) { 
    setUserCommand(commandText.getText()); 
} 

遊戲中的屬性更改偵聽器,然後會像這樣迴應:

gui.addPropertyChangeListener(new PropertyChangeListener() { 

    @Override 
    public void propertyChange(PropertyChangeEvent pcEvt) { 

     // is the property being changed the one we're interested in? 
     if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) { 

      // get user command: 
      String userCommand = pcEvt.getNewValue().toString(); 

      // then we can do with it what we want 
      play(userCommand); 

     } 

    } 
    }); 

public class WampusGUI extends JFrame { 
    public static final String USER_COMMAND = "user command"; 
    // .... 

    private void setUserCommand(String userCommand) { 
     String oldValue = this.userCommand; 
     String newValue = userCommand; 
     this.userCommand = userCommand; 
     firePropertyChange(USER_COMMAND, oldValue, newValue); 
    } 

那麼你就只能通過此setter方法改變這個字符串的值

這種技術的優點之一是觀察到的類,GUI不必具有關於觀察者類(遊戲)的任何知識。這是一個小的可運行的例子是這樣的:

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

public class WampusGUI extends JFrame { 
    public static final String USER_COMMAND = "user command"; 
    private String userCommand; 
    private JTextArea displayTextArea = new JTextArea(10, 30); 
    private JTextField commandText = new JTextField(10); 

    public WampusGUI() { 
     initComponents(); 
    } 

    private void setUserCommand(String userCommand) { 
     String oldValue = this.userCommand; 
     String newValue = userCommand; 
     this.userCommand = userCommand; 
     firePropertyChange(USER_COMMAND, oldValue, newValue); 
    } 

    private void initComponents() { 
     displayTextArea.setEditable(false); 
     displayTextArea.setFocusable(false); 
     JButton enterButton = new JButton("Enter Command"); 
     enterButton.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent evt) { 
      enterButtonActionPerformed(evt); 
     } 
     }); 
     JPanel commandPanel = new JPanel(); 
     commandPanel.add(commandText); 
     commandPanel.add(Box.createHorizontalStrut(15)); 
     commandPanel.add(enterButton); 

     JPanel mainPanel = new JPanel(); 
     mainPanel.setLayout(new BorderLayout()); 
     mainPanel.add(new JScrollPane(displayTextArea)); 
     mainPanel.add(commandPanel, BorderLayout.SOUTH); 
     add(mainPanel); 
    } 

    public void setTextArea(String text) { 
     displayTextArea.append(text); 
    } 

    private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) { 
     setUserCommand(commandText.getText()); 
    } 

    public static void main(String args[]) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      WampusGUI w = new WampusGUI(); 
      w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      w.pack(); 
      w.setLocationRelativeTo(null); 
      w.setVisible(true); 
      Game g = new Game(w); 
      g.play(); 
     } 
     }); 
    } 
} 

class Game { 
    private WampusGUI gui; 

    public Game(WampusGUI w) { 
     gui = w; 

     gui.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent pcEvt) { 

      // is the property being changed the one we're interested in? 
      if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) { 

       // get user command: 
       String userCommand = pcEvt.getNewValue().toString(); 

       // then we can do with it what we want 
       play(userCommand); 

      } 
     } 
     }); 
    } 

    public void play() { 
     gui.setTextArea("Welcome!\n"); 
     gui.setTextArea("Please enjoy the game!\n"); 
    } 

    public void play(String userCommand) { 
     // here we can do what we want with the String. For instance we can display it in the gui: 
     gui.setTextArea("User entered: " + userCommand + "\n"); 
    } 

} 
0

我喬恩斯基特同意,這是不是一個很好的解決方案......

但如果ü想的骯髒的解決方案,以烏爾問題,那麼U可以試試這個:在其他

public class wampusGUI extends javax.swing.JFrame 
{ 
    private static wampusGUI myInstance; 
    public wampusGUI() 
    { 
     myInstance = this; 
     initComponents(); 
    } 

    public static void getUserCommand() 
    { 
     if(myInstance!=null) 
     { 
      return myInstance.commandText.getText(); 
     } 
     else 
     { 
      return null; 
     } 
    } 
    ...... 
    ...... 
} 

類使用:

public void play() 
{ 
    ..... 
    //String s = userCommand; // here value should come should 
    String s = wampusGUI.getUserCommand(); 
    ..... 
} 

這種代碼是在我們的一些遺留項目中......我討厭這個。在你的代碼

+0

這沒有必要,並有更多優雅的解決方案。 –

+0

我從來沒有告訴過這是一個優雅的解決方案;) –

+0

是的。我想這取決於程序員是否希望通過偵聽器推送數據或通過輪詢拉取數據。如果可能的話,我更喜歡聽者的方法,但這並不總是可行的。 –

4

看,它似乎要顯示的對話框到您的用戶具有一定的文字

gui.setTextArea(welcome()); 
gui.setTextArea(describe()); 

有時,該對話框應該捕獲它之後處理用戶輸入。

  1. 那些setTextArea調用不是你想要使用的。用戶將永遠不會看到歡迎消息,因爲它將立即被描述消息取代。
  2. 確保您不會阻止事件發送線程(EDT),否則什麼也不會顯示。我不知道你的Command課程會做什麼,但我看到Event Dispatch Thread上的一個無限循環,這從來都不是好事。請看Concurrency in Swing tutorial以獲取更多信息
  3. 由於for循環,用戶將無法輸入任何命令,因爲EDT正忙於處理您的循環。你需要的是一個阻塞調用,允許用戶提供輸入(而不是阻塞EDT,但只是阻止你的代碼執行)。 JOptionPane類中的靜態方法非常適用於此(例如JOptionPane#showInputDialog)。這些方法還有一個機制,可以將用戶輸入返回給調用代碼,而不需要任何靜態變量,這可以解決您的問題。