2012-09-13 8 views
5

私は同じパッケージに2つのクラスを持っています。あるクラスでstatic variableを宣言し、別のクラスのその変数にアクセスしたいとします。ここで 他のクラスから静的変数にアクセス

は私が

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"); 
    } 
} 

しかし、変数にアクセスしたいコードがある静的変数ここ

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

に宣言しているに私のコードですが、私は最初から変数を渡すことができますクラスを引数として使用します。しかし、問題は、私がプログラムを実行するとき、値が最初にnullになることです。これは必要ありません。私はtextfieldに値を入力するときに、別のクラスに行く必要があります。

ありがとうございます。私は、これは良い解決策ではないことをジョンスキートに同意

+7

"値は最初にnullになります"とはどういう意味ですか?基本的には、デザインを変更する必要があります。グローバル変数は本当に良い解決策ではありません。 –

+1

私は@jonに同意します。あなたの文字列は、ユーザがそれを変更する機会があるまで、まともな値を持たないでしょう。また、あなたの永遠のforループは、Swingアプリケーションのための良いデザインではありません。あなたが実際にJTextFieldの状態を変更してからこれを実行するのを聞くためにリスナーを使用したいのではないかと思います。おそらく、Swing Timerを使用することも検討したいと思うかもしれませんが、あなたのプログラムについてもっと知り、それが何をすべきかを知るまでは分かりません。 –

+0

教えてください:このコードで何をしようとしていますか? –

答えて

2

ゲームオブジェクトがGUIオブジェクトの状態の変化をリッスンして応答できるように、ある種のリスナーを使用することをお勧めします。これを行うにはいくつかの方法がありますが、私が見つけた最もエレガントで便利なのは、Swing独自のPropertyChangeSupportを使用してPropertyChangeListenersを使用できるようにすることです。すべてのSwingコンポーネントでPropertyChangeListenerを追加できます。そして私はあなたがゲームがそうのように(大文字であるべきである)あなたのWampusGUIクラスにオブジェクトを1を追加したことを、あなたがこれを行うことを示唆している:

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メソッドを経由して、この文字列の値を変更します

このテクニックの美しさの1つは、観察されたクラスの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がウル問題に汚いソリューションは、その後、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. Event Dispatch Thread(EDT)をブロックしないでください。何も表示されません。あなたのCommandクラスが何をするのか分かりませんが、決して良いことではないEvent Dispatch Threadに無限ループがあります。詳細については、Concurrency in Swing tutorialをご覧ください。
  3. forループのおかげで、EDTがループ処理中であるため、ユーザはコマンドを入力できなくなります。必要なのは、ブロッキングコールで、ユーザーが入力を提供できるようにします(EDTをブロックするのではなく、コードの実行をブロックする)。 JOptionPaneクラスの静的メソッドは、これに完全に適しています(例えば、JOptionPane#showInputDialog)。これらのメソッドには、静的変数を使用せずにユーザー入力を呼び出しコードに戻すメカニズムがあり、問題が解決されます。
関連する問題