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");
}
}
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. –
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. –
Per favore, dicci: cosa stai cercando di fare con questo codice? –