2012-09-13 15 views
5

Tengo dos clases en el mismo paquete. He declarado static variable en una clase y quiero acceder a esa variable en otra clase.Acceder a la variable estática de otra clase

Aquí está mi código en el que he declarado la variable estática

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

Aquí está el código en el cual quiero acceder a la variable de

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

Sin embargo, me puede pasar la variable de primera clase como argumento pero el problema es que, cuando ejecute el programa, el valor va a ser nulo la primera vez, lo que no quiero. Quiero cuando ingreso valor en textfield, entonces debería ir a otra clase.

Gracias.

+7

¿Qué quiere decir con "el valor va nulo por primera vez"? Básicamente, debe cambiar su diseño: tener una variable global es realmente * no * una buena solución. –

+1

Estoy de acuerdo con @jon. Su cadena no tendrá un valor decente hasta que el usuario haya tenido la oportunidad de cambiarla. Además, su bucle for forever no es un buen diseño para una aplicación Swing. Me pregunto si realmente quieres usar un oyente para escuchar si el usuario está cambiando el estado de JTextField y luego actúa sobre esto. Sin embargo, quizás también desee estudiar el uso de un temporizador de oscilación, aunque es difícil de saber hasta que sepamos más sobre su programa y lo que se supone que debe hacer. –

+0

Cuéntanos: ¿qué intentas hacer con este código? –

Respuesta

2

Le sugiero que utilice un oyente de un tipo u otro para permitir que el objeto Game escuche y responda a los cambios en el estado del objeto GUI. Hay varias formas de hacerlo, pero una de las más elegantes y útiles que he encontrado es usar el PropertyChangeSupport propio de Swing para permitirle usar PropertyChangeListeners. Todos los componentes Swing le permitirán agregarle PropertyChangeListener.Y por lo que sugiero que lo haga, que tiene juegos agregue a su clase WampusGUI (que debe ser capitalizado) objeto de este modo:

public Game(WampusGUI w) { 
    gui = w; 

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

Esto permitirá Juego para escuchar los cambios en el estado de la interfaz gráfica de usuario.

A continuación, deberá hacer que la guia userCommand de la interfaz sea una "propiedad vinculada", lo que significa darle un método setter que active el soporte de cambio de propiedad notificando a todos los oyentes del cambio. Me gustaría hacer esto de esta manera:

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

Entonces sólo iba a cambiar el valor de esta cadena a través de este método de selección:

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

cambio de propiedad de detectores del juego sería entonces responder de esta manera:

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

     } 

    } 
    }); 

Una de las bellezas de esta técnica es que la clase observada, la GUI, no tiene que tener ningún conocimiento sobre la clase del observador (el Juego). Un pequeño ejemplo ejecutable de esto es así:

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

Estoy de acuerdo con Jon Skeet que esto no es una buena solución ...

Pero en el caso u desea una solución sucia a problema ur entonces u puede intentar esto:

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; 
     } 
    } 
    ...... 
    ...... 
} 

en el otro su uso en clase:

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

este tipo de código hay en algunos de nuestros proyectos heredados ... y me gusta esta.

+0

No hay necesidad de esto, y hay soluciones mucho más elegantes. –

+0

Nunca dije que esta es una solución elegante;) –

+0

Es cierto. Supongo que depende si el programador quiere que los datos se envíen a través de un oyente o se extraigan mediante sondeo. Si es posible, prefiero el enfoque del oyente, pero esto no siempre es posible. –

4

En cuanto a su código, parece que desea mostrar cuadros de diálogo para el usuario con un determinado texto

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

y, a veces, que el diálogo debe capturar la entrada del usuario que se maneja después.

  1. Esas llamadas setTextArea no son lo que desea utilizar. El usuario nunca verá el mensaje de bienvenida ya que será inmediatamente reemplazado por el mensaje de descripción.
  2. Asegúrese de no bloquear el hilo de envío de evento (EDT) o no se mostrará nada. No sé lo que hará su clase Command, pero veo un ciclo infinito en el Event Dispatch Thread que nunca es algo bueno. Eche un vistazo a Concurrency in Swing tutorial para más información
  3. Gracias a ese bucle for, el usuario simplemente no podrá ingresar ningún comando ya que el EDT está ocupado manejando su ciclo. Lo que necesita es una llamada de bloqueo que le permita al usuario proporcionar información (no bloqueando el EDT, sino simplemente bloqueando la ejecución de su código). Los métodos estáticos en la clase JOptionPane son perfectamente adecuados para esto (por ejemplo, JOptionPane#showInputDialog). Estos métodos también tienen un mecanismo para pasar la entrada del usuario al código de llamada sin ninguna variable estática, lo que resuelve su problema.
Cuestiones relacionadas