2012-09-13 22 views
5

Ho due classi nello stesso pacchetto. ho dichiarato un static variable in una classe e voglio accedere a quella variabile in un'altra classe.Accesso a variabili statiche di un'altra classe

Ecco il mio codice in cui ho dichiarato la variabile statica

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

Ecco il codice in cui voglio accedere variabile

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

Tuttavia, posso passare la variabile dalla prima classe come argomento. ma il problema è che, quando eseguirò il programma, il valore andrà a zero prima volta, cosa che non voglio. Voglio quando inserisco il valore in textfield quindi dovrebbe passare a un'altra classe.

Grazie.

+7

Che cosa intendete per "il valore sta andando a zero prima volta"? Fondamentalmente dovresti cambiare il tuo design - avere una variabile globale non è * davvero * una buona soluzione. –

+1

Sono d'accordo con @jon. La tua stringa non avrà un valore accettabile finché l'utente non avrà la possibilità di cambiarla. Anche il tuo ciclo per sempre non è un buon progetto per un'applicazione Swing. Mi chiedo se vuoi davvero usare un listener invece per ascoltare che l'utente sta cambiando lo stato di un JTextField e poi agisce su questo. Forse dovresti anche cercare di usare uno Swing Timer, difficile da sapere fino a quando non sapremo di più sul tuo programma e su cosa dovrebbe fare. –

+0

Per favore, dicci: cosa stai cercando di fare con questo codice? –

risposta

2

Suggerisco di utilizzare un listener di un tipo o dell'altro per consentire all'oggetto Game di ascoltare e rispondere alle modifiche nello stato dell'oggetto GUI. Ci sono diversi modi per farlo, ma uno dei più eleganti e utili che ho trovato è quello di utilizzare PropertyChangeSupport innato di Swing per consentire di utilizzare PropertyChangeListeners. Tutti i componenti Swing ti consentiranno di aggiungere un PropertyChangeListener ad esso.E così suggerire che si esegue questa operazione, che si dispone di Gioco aggiungere uno alla classe WampusGUI (che dovrebbe essere capitalizzata) oggetto in questo modo:

public Game(WampusGUI w) { 
    gui = w; 

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

Questo permetterà gioco di ascoltare per cambiamenti nello stato del gui.

Vorrete quindi rendere la stringa userCommand del gui String una "proprietà associata" che significa assegnargli un metodo setter che attiva il supporto delle modifiche delle proprietà che notifica a tutti gli ascoltatori di modifiche. Vorrei farlo in questo modo:

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

allora si avrebbe solo cambiare il valore di questa stringa tramite questo metodo setter:

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

modifica della proprietà ascoltatore del gioco sarebbe quindi rispondere in questo modo:

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 delle bellezze di questa tecnica è che la classe osservata, la GUI, non deve avere alcuna conoscenza della classe di osservatori (il Gioco). Un piccolo esempio eseguibile di questo è il seguente:

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

Sono d'accordo con Jon Skeet che questa non è una buona soluzione ...

Ma nel caso in cui u vuole una soluzione sporca al problema ur poi u può provare questo:

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

nell'altra classe di utilizzo:

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

questo tipo di codice è lì in alcuni dei nostri progetti legacy ... e io odio questo.

+0

Non ce n'è bisogno e ci sono soluzioni molto più eleganti. –

+0

non ho mai detto che questa è una soluzione elegante;) –

+0

Vero. Immagino che dipenda se il programmatore vuole che i dati vengano trasmessi tramite un listener o estratti tramite polling. Se possibile, preferisco l'approccio dell'ascoltatore, ma non è sempre possibile farlo. –

4

Guardando il codice, sembra che si desidera visualizzare le finestre di dialogo per l'utente con un determinato testo

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

e, a volte, che il dialogo deve catturare l'input dell'utente che viene gestito in seguito.

  1. Quelle chiamate setTextArea non sono quelle che si desidera utilizzare. L'utente non vedrà mai il messaggio di benvenuto poiché verrà immediatamente sostituito dal messaggio descrittivo.
  2. Assicurarsi di non bloccare il thread Event Dispatch (EDT) o nulla verrà mostrato a tutti. Non so cosa farà la tua classe Command, ma vedo un ciclo infinito su Event Dispatch Thread che non è mai una buona cosa. Date un'occhiata allo Concurrency in Swing tutorial per ulteriori informazioni
  3. Grazie a quel ciclo for, l'utente semplicemente non sarà in grado di immettere alcun comando mentre l'EDT è impegnato a gestire il loop. Quello di cui hai bisogno è una chiamata di blocco che permetta all'utente di fornire input (non bloccando l'EDT, ma semplicemente bloccando l'esecuzione del tuo codice). I metodi statici nella classe JOptionPane sono perfettamente adatti per questo (ad esempio lo JOptionPane#showInputDialog). Questi metodi hanno anche un meccanismo per passare l'input dell'utente al codice chiamante senza alcuna variabile statica, che risolve il problema.
Problemi correlati