statsButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){

              //Return the string "stats" to gameLoop() as cmd
            }
        }); 

public void gameLoop(){
        Scanner lineScanner = new Scanner(System.in);
        cmd = "";

        System.out.print(getBoard().printBoard(false));

        while (!cmd.equals("quit")) {
            System.out.print(">");
            Scanner wordScanner = new Scanner(lineScanner.nextLine());

        if (wordScanner.hasNext()) {
            cmd = wordScanner.next();
            if (cmd.equals("board")) {
                System.out.print(getBoard().printBoard(false));
                } else if (cmd.equals("ships")) {
            System.out.print(getBoard().printBoard(true));
                } else if (cmd.equals("help")) {
                    printHelp();    
                } else if (cmd.equals("stats")) {
                    printStats();
                } else if (cmd.equals("fire")) {
            if(fire(wordScanner)) { 
            printStats();
            cmd = "quit";
                    }
                } else if (cmd.equals("quit")) {    
                } else if (!cmd.equals("")) {
                    System.out.println(ILLEGAL_COMMAND);
                }
            }

        }
    }

Что я пытаюсь сделать, так это то, что когда пользователь нажимает кнопку statsButton, String cmd в gameLoop будет изменен на «stats». statsButton и gameLoop() находятся в двух разных классах. Кто-нибудь может дать мне представление, как это сделать? (Я пробовал pipedreader/pipedwriter), и я просто не могу понять это правильно.

* В основном я пытаюсь превратить свое консольное приложение в приложение с графическим интерфейсом, не меняя исходное консольное приложение.

Изменить: что я пробовал

Class textBased 
PipedInputStream in = new PipedInputStream()

public void gameLoop(){
    try{
        in.connect(GUIclass.out);

    Scanner lineScanner = new Scanner(in);`

Class GUIclass  
    PipedOutputStream out = new PipedOutputStream();
    PrintWriter writer;

  public GUIclass(){
    final PrintWriter writer = new PrintWriter(out);
    statsButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){

              writer.println("stats");
             }
          }); 

Это то, что я пытался написать, но это, похоже, не работает.

2
rlhh 13 Ноя 2011 в 02:03
 – 
mKorbel
13 Ноя 2011 в 21:41

4 ответа

Что касается

В основном я пытаюсь превратить свое консольное приложение в приложение с графическим интерфейсом, не меняя исходное консольное приложение..."

Мой совет прост: «Не делай этого».

Два приложения имеют совершенно разную структуру: одно линейное, другое управляемое событиями, и их нельзя напрямую перевести друг в друга. Лучше создать новую программу с графическим интерфейсом с нуля. Теперь, если ваше приложение без графического интерфейса содержит некоторые хорошо структурированные и управляемые объектно-ориентированные классы, то во что бы то ни стало используйте эти классы в разделе «модель» или логика вашего графического интерфейса, но не пытайтесь напрямую преобразовать поток программы одного типа. применения к другому.

Изменить
На основании ваших опубликованных требований:

«Вы должны иметь возможность играть в свою игру Battleship через свой графический интерфейс. Кроме того, текстовый интерфейс, который вы написали для проекта 1, должен по-прежнему «работать» и быть играбельным».

Поправьте меня, если я ошибаюсь, но держу пари, что здесь задействовано несколько классов, и только один из них — «текстовый интерфейс». Если это так, то используйте не интерфейсные классы в качестве модели вашего графического интерфейса, как я предложил выше, но не используйте текстовый интерфейс для чего-либо, связанного с графическим интерфейсом, и не пытайтесь эмулировать его в своем графическом интерфейсе.

4
Hovercraft Full Of Eels 13 Ноя 2011 в 02:23
Я понимаю о том, чтобы не делать этого, я также больше привык этого не делать. Однако в этом случае в спецификации указано, что я должен это сделать.
 – 
rlhh
13 Ноя 2011 в 02:11
«Вы должны иметь возможность играть в свою игру Battleship через свой графический интерфейс. Кроме того, текстовый интерфейс, который вы написали для проекта 1, должен по-прежнему «работать» и быть играбельным».
 – 
rlhh
13 Ноя 2011 в 02:20
@ user1043625: см. обновление к моему ответу выше. Кроме того, подумайте о том, чтобы отредактировать свой профиль и дать себе менее общее имя на форуме, надеюсь, лучше, чем мое. :)
 – 
Hovercraft Full Of Eels
13 Ноя 2011 в 02:22
У меня есть несколько классов, и все выходные данные обрабатываются одним классом. Однако нам говорят передавать ввод из графического интерфейса в консоль, а не создавать что-либо отдельно.
 – 
rlhh
13 Ноя 2011 в 02:26
@ user1043625: нет, вам не сказали передать ввод из графического интерфейса в консоль, если вы получили такие инструкции. Все, что в нем указано, это играть в игру через графический интерфейс, то есть использовать доступные классы, и в консольную игру все равно можно будет играть. Это означает, что вы не должны изменять неконсольные классы таким образом, чтобы сделать интерфейс консоли неиграбельным. Это большая разница. Я по-прежнему придерживаюсь того, что я заявляю в своем ответе.
 – 
Hovercraft Full Of Eels
13 Ноя 2011 в 03:03

Попросите консольное приложение создать экземпляр кнопки ActionListener и передать его пользовательскому интерфейсу. Когда событие действия запускается, слушатель сообщит консольному приложению, что это произошло. Метод в ActionListener скажет ему, что делать.

3
duffymo 13 Ноя 2011 в 02:05
Я не совсем понимаю, можете ли вы объяснить на нескольких простых примерах? Кроме того, я думаю, что это будет изменение исходного класса, чего я не должен делать.
 – 
rlhh
13 Ноя 2011 в 02:11
"Не положено" - почему бы и нет?
 – 
duffymo
13 Ноя 2011 в 02:18
«Вы должны иметь возможность играть в свою игру Battleship через свой графический интерфейс. Кроме того, текстовый интерфейс, который вы написали для проекта 1, должен по-прежнему «работать» и быть играбельным».
 – 
rlhh
13 Ноя 2011 в 02:27
Ваши текстовые и графические пользовательские интерфейсы должны быть отдельными. Я предполагаю, что вы должны иметь возможность выбирать между двумя. Это будет означать модификацию оригинала. Ваш профессор пытается заставить вас полностью отделить игровую логику от презентации. Вашей игровой логике должно быть передано то, что ей нужно. Он не должен знать, получает ли он текст или графический интерфейс.
 – 
duffymo
13 Ноя 2011 в 02:50

Я согласен с комментарием Hovercrafts (изменен на ответ).

Но в целом для подобных проблем я бы изменил сигнатуру метода вашего gameLoop(). Я хотел бы использовать:

public void gameLoop(Reader reader)

Затем вы можете передавать в цикл разные типы считывателей в зависимости от требований.

Для консоли вы можете сделать что-то вроде:

gameloop( new InputStreamReader( System.in ) );

Для графического интерфейса вы можете сделать что-то вроде:

gameLoop ( new StringReader("some text") );

Редактировать:

Не изменяя сигнатуру метода, вы можете перенаправить System.in на строку, полученную с помощью ActionListener:

public class Test
{
    public static void main(String args[]) throws Exception
    {
        String text = "some text";
        System.setIn( new ByteArrayInputStream( text.getBytes() ) );
        // gameloop(); 
        Scanner lineScanner = new Scanner(System.in);
        System.out.println( lineScanner.nextLine() );
    }
}
3
camickr 13 Ноя 2011 в 02:35
Я добавил кое-что выше, чтобы показать вам, что я пробовал, но, похоже, это не работает для меня. Не уверен, что я делаю неправильно.
 – 
rlhh
13 Ноя 2011 в 02:47
@ user1043625, я не понимаю вашего комментария. Почему бы вам не попробовать то, что я предложил, поскольку это рабочий код. Я не предлагал использовать PipedStream, поэтому не знаю, что не так с вашим кодом.
 – 
camickr
13 Ноя 2011 в 07:50

Если у вас что-то вроде этого:

class B {
 public void gameLoop(){
  ..
 }
}

А также

class A{

  statsButton.addActionListener(new ActionListener() {
            ...
        }); 
}

Вы можете объявить ссылку на B в A с помощью final . В этом случае он будет виден во внутреннем классе ActionListener.

class A{
  final B b = ...; //final variable is visible in inner class
  statsButton.addActionListener(new ActionListener() {
            b.gameLoop();
             ...
        }); 
}
1
Sergey Gazaryan 13 Ноя 2011 в 02:11
У меня есть что-то похожее на то, что вы написали. Но проблема в том, как мне изменить String cmd, когда я нажимаю кнопку? b.gameLoop().cmd не сработает, и я не думаю, что мне следует это делать.
 – 
rlhh
13 Ноя 2011 в 02:20