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");
}
}
¿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. –
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. –
Cuéntanos: ¿qué intentas hacer con este código? –