将Swing集成到一个简单的文本冒险游戏中

时间:2016-08-02 04:43:45

标签: java swing jframe actionlistener jtextfield

我对Java中的一些中间概念相当新。最近我做了一个名为DazzleQuest的文本冒险游戏,完全在开发者控制台/终端中运行。它涉及我的朋友作为角色所以我想通过将命令行的功能和控制台的输出转移到由JTextArea组成的简单Swing界面来向他们展示并获得Java经验,以显示游戏的输出以及JTextFieldActionListener来处理来自用户的命令。

我的主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 个答案:

答案 0 :(得分:2)

首先,关于包含代码,您应该看看https://stackoverflow.com/help/mcve如何帮助我们。

现在,鉴于您还没有提供任何代码(但是!)提供有关如何构建程序的建议,这有点棘手。但是,无论如何,我都会尝试进行尝试,并在您提供MWE时编辑答案。

在您的情况下,JTextArea实际上只是一个花哨的System.out.print,因为您只会用它来显示您的冒险游戏输出的文本(如果我正确理解您)。基本上,您可以编写一个接受字符串的方法,该方法会将该字符串附加到JTextArea。然后用这种方法替换当前的输出行。

然后你有JTextField你要用Scanner(System.in)代替你Entersubmit。我假设您知道如何设置响应run()interface - 按钮的动作侦听器。 如何设置它们并不是那么奇怪,许多指南都在谈论如何做到这一点。 https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html给出了一个很好的例子。

现在,一般来说,关于程序的结构。 您希望依赖用户输入文本的方式或如何显示文本。我的意思是你不希望输入或显示逻辑干扰你的游戏(商业)逻辑。您的游戏逻辑应该只从任何地方接收输入,并将其输出到任何地方。然后,调用函数决定如何以及如何处理信息并不是为了关注游戏逻辑。

因此,应用于您发布的方法名称。我认为print(string)是你开球的地方。由于您总是希望显示输出,您可能希望在此处传递System.out,其中包含方法JTextArea(或类似方法),该方法应该是将文本打印到任何文本的方法-element用于显示文本,无论是run()还是handleCommand()actionPerformed()方法永远不需要知道。 Thread也应该只接受一个值(我假设一个字符串)并按照它应该处理它,无论是谁或什么叫它。

我在没有代码的情况下给你提供更多建议时遇到了麻烦。但我的一般建议是:不要将表示逻辑与业务逻辑混合在一起。并且尽可能少地给每个方法提供信息,因为给予它们超出它们实际需要的数量通常会导致流动性和结构不那么灵活。

编辑,现在添加了一些代码。

  

我知道如何将输出打印到JTextArea而不是控制台。我的问题是如何让handleCommand()与Frame类

中的actionPerformed()一起使用

采用... 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()使用您的应用程序(多人游戏?),您将不必费心。 https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html提供了有关如何编写监听器的一些很好的信息。但我也会给你一些建议代码。

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)只是将字符串发送到它的绘图区域,即{{1}或commandHandler

handle(string)是新的。这是你的游戏逻辑应该在的地方。它有一个方法handleCommand(string),它是您的旧continue()。它有一个返回布尔值的events()方法。每当您希望故事继续时,例如当用户输入命令时,布尔值应设置为true。最后run()(这是一个坏名称)返回自上一个命令发送以来发生的事情,并为用户提供下一步操作的选项。我没有做过那样的实现,因为我只是想给你这个概念。用户界面不进行任何逻辑处理。 continue()方法并不期望任何内容,它只会检查commandHandler是否为真。 Thread是所有bizz的所在。

现在,你确实有一个无限循环运行。因此,如果您遇到任何性能问题,可以查看{{1}}。这个模型应该支持转移它。