Интеграция Swing в простую текстовую приключенческую игру

Я довольно плохо знаком с некоторыми промежуточными понятиями в Java. Недавно я создал текстовую приключенческую игру под названием DazzleQuest, которая полностью работает в консоли разработчика / терминале. В нем участвуют мои друзья в качестве персонажей, поэтому я хотел показать им это и получить опыт работы с Java, передав функциональность командной строки и вывод с консоли на простой интерфейс Swing, состоящий изJTextArea чтобы показать результат игры иJTextField, сActionListener, чтобы обрабатывать команды от пользователя.

Мой основнойDazzleQuest класс содержит методы, называемыеrun() а такжеhandleCommand()Я считаю, что мне нужно интегрировать с моимFrame класс и его подклассTextFieldHandler [который расширяетсяActionListener].Мне вообще интересно, как лучше интегрировать эти методы и классы. Мои нынешние попытки сбивают с толку, и, хотя у меня есть базовые знания о том, как заставить различные классы и методы общаться, это является предварительным.

Извиняюсь за многословность и отсутствие конкретики. Я хотел бы поделиться своим кодом, но не уверен, сколько и что именно дать. Если вы думаете, что можете ответить на мой вопрос, но вам нужен пример того, что у меня есть, скажите, пожалуйста. Даже псевдокод в качестве ответа был бы оценен. Спасибо! Понимание этого может быть очень полезным для моего образования в качестве программиста.

РЕДАКТИРОВАТЬ: Вот упрощенные примеры моего кода из версии игры, которая полностью работает в консоли разработчика. Это мой основной классDazzleQuest:

public class DazzleQuest {

public void run() {
    listCommands();
    for (;;) {
        StdOut.println(new StringBuilder("You are in ").append(currentRoom.getName()).append(".").toString());
        StdOut.println(new StringBuilder("You can go to: ").append(currentRoom.listExits()).toString());
        StdOut.print("> ");
        handleCommand(StdIn.readLine());
        StdOut.println();
    }

public void handleCommand(String line) {
        String[] words = line.split(" ");
        if (words[0].equals("look"))
            look();
        }
    }

}

А вот мой токJFrame настройки, вFrame учебный класс:

import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JTextArea;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Frame extends JFrame {

    public static JTextField field;
    public JTextArea area;

    public Frame() {
        setLayout(new FlowLayout());

        area = new JTextArea(20, 40);
        area.setEditable(false);

        field = new JTextField(20);
        add(area);
        add(field);
        pack();
        setVisible(true);

         TextFieldHandler handler = new TextFieldHandler();

            field.addActionListener(handler);
        }

        public class TextFieldHandler implements ActionListener{

            public void actionPerformed(ActionEvent event)
            {
                String line = field.getText();
                area.append(line + "\n");
                field.setText("");
            }
        }


    public static void main(String args[]) {

        Frame test = new Frame();
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Я знаю, как распечатать вывод наJTextArea вместо консоли. Моя проблема в том, как именно получитьhandleCommand() работать сactionPerformed() вFrame класс, или я должен установить слушателя действия в основном классе или что-то в этом роде. Любые примеры реализации будут с благодарностью.

Еще раз спасибо за все, что вы можете сказать мне!

Ответы на вопрос(1)

Решение Вопроса

https://stackoverflow.com/help/mcve о том, как помочь нам помочь вам.

Теперь, учитывая, что вы не предоставили никакого кода (пока!), Дающего советы о том, как вы должны структурировать свою программу, это немного сложно. Но я все равно попробую и, возможно, отредактирую ответ, когда вы предоставите MWE.

В твоем случае,JTextArea это действительно просто фантазияSystem.out.print так как вы будете использовать его только для отображения текста, который выводит ваша приключенческая игра (если я вас правильно понимаю). Таким образом, вы можете написать метод, который принимает строку, и этот метод добавит эту строку к вашемуJTextArea, Затем просто замените ваши текущие выходные строки этим методом.

Тогда у вас естьJTextField который вы хотите заменить своим (я предполагаю)Scanner(System.in) с. Я предполагаю, что вы знаете, как настроить слушатель действия, который отвечает наEnter илиsubmit-кнопка. Как это настроить, не так уж и странно, и многие гиды рассказывают, как это сделать.https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html дает хороший пример.

Теперь в целом относительно структуры вашей программы. Ты сделаешьне хочу быть зависимым откак пользователь вводит текст или как вы его отображаете. Я имею в виду, что вы не хотите, чтобы логика ввода или отображения вмешивалась в вашу игру (бизнес) логика. Ваша игровая логика должна просто получать входные данные из любого места и выводить их в любое место. То, как и что решают делать вызывающие функции с информацией, не заботит логика игры.

Итак, применимо к именам методов, которые вы разместили. Я предполагаюrun() это то, где вы начинаете. Поскольку у вас есть вывод, который вы всегда хотите отобразить, вы можете передатьinterface здесь есть методprint(string) (или тому подобное), который должен быть методом, который печатает текст на любом текстовом элементе, используемом для отображения текста, будь тоSystem.out или жеJTextArea,run() метод никогда не должен знать.handleCommand() также следует просто принять значение (я предполагаю строку) и обработать его так, как оно должно, независимо от того, кто или что вызвал его.

У меня проблемы с тем, чтобы дать вам больше советов без кода. Но моя общая рекомендация: не смешивайте логику представления с бизнес-логикой. И предоставьте каждому методу как можно меньше информации, потому что предоставление им большего, чем им действительно нужно, обычно приводит к менее гибкому процессу и структуре.

РЕДАКТИРОВАТЬ теперь, когда был добавлен некоторый код.

Я знаю, как распечатать вывод на JTextArea, а не на консоль. Моя проблема заключается в том, как именно заставить handleCommand () работать с actionPerformed () в классе Frame

Перейти сactionPerformed() подход. Я рекомендую это, потому что вам не придется так сильно беспокоиться, если вы решитеThread Ваше приложение когда-нибудь в будущем (мультиплеер?).https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html дает хорошую информацию о том, как написать своему слушателю. Но я также дам вам код предложения.

...
area.setEditable(false);

field = new JTextField(20);
field.addActionListener(new SendText());    
....

class SendText implements ActionListener{
    public void actionPerformed(ActionEvent ae){
        if(ae.getSource() == field){
            String str = field.getText();
            if(!str.equals("")){
                commandHandler.handle(str);
            }
        }
    }
}

А потом переписать свойrun() метод

public void run(){
   ui.print(commandHandler.listCommands());

   while(true){
       if(commandHandler.continue()){
           ui.print(commandHandler.events());
       }
   }
}

Так что теперь у вас очень маленькийrun() метод, который не имеет реальной привязки ни к логике, ни к дисплею.ui.print(str) это метод, который вашUI учебный класс (Frame в вашем случае), который просто добавляет то, что когда-либо строка отправляется в его область рисования, будь тоSystem.out илиJTextArea.

commandHandler новый. Вот где должна быть ваша игровая логика. У него есть методhandle(string) какой твой старыйhandleCommand(string), Оно имеетcontinue() метод, который возвращает логическое значение. Логическое значение должно быть установлено в true, когда вы хотите, чтобы история продолжалась, например, когда пользователь вводит команду. И наконецevents() (что является плохим именем), которое возвращает то, что произошло с момента отправки последней команды, и дает пользователям варианты того, что делать дальше. Я не реализовал это, так как просто хочу дать вам концепцию. Пользовательский интерфейс не выполняет никакой логической обработки.run() метод ничего не ожидает, он просто проверяет,continue() правда.commandHandler там, где все бизз.

Теперь у вас есть бесконечный цикл. Так что, если у вас возникнут проблемы с производительностью, вы можете изучитьThread, Эта модель должна поддерживать переход к ней.

 speers04 авг. 2016 г., 06:40
Я думаю, что я почти там! Любой совет о том, как написать метод continue ()?
 speers02 авг. 2016 г., 08:52
Большое спасибо за ваш ответ! Разделение представления и бизнес-логики является для меня интригующей темой - я однажды создал игру, следуя примеру, в котором класс «Модель», содержащий правила и логику игры, был отделен от основного класса игры, который содержал методы отображения, элементы управления и начало и конец игры. Это разница, которую вы имеете в виду? Я постараюсь повторить примеры моих реализаций завтра и сделаю более конкретные предложения возможными!
 Chewtoy02 авг. 2016 г., 09:46
@ Сперс Да. Это звучит как то, что я имею в виду.MVC Шаблон довольно стандартный, и на то есть веские причины. Это значительно упрощает замену пользовательского интерфейса без изменения логики обработки данных.
 speers02 авг. 2016 г., 23:57
Я запомню это. Моя текущая программа довольно проста, и я думаю, что могу легко отделить модель от дисплея, но, вероятно, сделаю это после того, как выясню, как заставить ее работать в графическом интерфейсе. Я только что обновил свой пост примерами кода, так что если бы вы могли взглянуть еще раз, это было бы просто потрясающе!
 speers04 авг. 2016 г., 07:10
Неважно, думаю, я делаю успехи - Большое спасибо за вашу помощь.
 Chewtoy03 авг. 2016 г., 10:41
@speers Проверьте мои правки. Я дал несколько предложений, которые, я надеюсь, не будут слишком запутанными, чтобы понять или реализовать.

Ваш ответ на вопрос