Proponuję użyć detektora jednego lub drugiego rodzaju, aby umożliwić obiektowi Game nasłuchiwanie i reagować na zmiany w stanie obiektu GUI. Istnieje kilka sposobów, aby to zrobić, ale jednym z najbardziej eleganckich i użytecznych, jakie znalazłem, jest wykorzystanie własnego wrodzonego PropertyChangeSupport Swinga, aby umożliwić korzystanie z PropertyChangeListeners. Wszystkie komponenty Swing umożliwiają dodanie do niego obiektu PropertyChangeListener.A więc proponuję, aby to zrobić, że trzeba Gra dodasz do swojej klasy WampusGUI (które powinny być kapitalizowane) obiektu tak:
public Game(WampusGUI w) {
gui = w;
gui.addPropertyChangeListener(new PropertyChangeListener() {
// ....
}
Pozwoli to gra do nasłuchiwania zmian w stanie GUI za.
Będziesz wtedy chciał, aby komenda użytkownika GUI była "właściwością związaną", co oznacza, że daje ona metodę ustawiającą, która będzie uruchamiała obsługę zmiany właściwości, powiadamiając wszystkich odbiorców o zmianie. Chciałbym zrobić to tak:
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);
}
Następnie należy zmienić wartość tylko ten ciąg za pośrednictwem tej metody setter:
private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) {
setUserCommand(commandText.getText());
}
zmiana nieruchomość słuchacz Gra byłaby następnie odpowiedzieć tak:
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);
}
}
});
Jedną z piękności tej techniki jest to, że obserwowana klasa, GUI, nie musi mieć żadnej wiedzy o klasie obserwatorów (Grze). Niewielki, działający przykład tego jest następujący:
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");
}
}
Co masz na myśli, mówiąc, że "wartość jest równa zeru"? Zasadniczo powinieneś zmieniać projekt - posiadanie zmiennej globalnej naprawdę nie jest dobrym rozwiązaniem. –
Zgadzam się z @jon. Twój ciąg nie będzie miał przyzwoitą wartość, dopóki użytkownik nie będzie miał szansy go zmienić. Również twoja pętla forever for nie jest dobrym projektem dla aplikacji Swing. Zastanawiam się, czy naprawdę chcesz użyć detektora zamiast tego, aby słuchać, że użytkownik zmienia stan JTextField, a następnie działa w tym kierunku. Być może będziesz także chciał zaglądać do gry używając Swing Timer, ale trudno się z nim zapoznać, dopóki nie dowiemy się więcej o twoim programie io tym, co powinien zrobić. –
Poinformuj nas: co próbujesz zrobić z tym kodem? –