【问题标题】:Passing input from JButton to console将输入从 JButton 传递到控制台
【发布时间】:2011-12-27 19:38:33
【问题描述】:
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 时,gameLoop 中的 String cmd 将更改为“stats”。 statsButton 和 gameLoop() 位于两个不同的类中。任何人都可以给我一个想法如何做到这一点? (我尝试过 pipedreader/pipedwriter),但我似乎无法做到正确。

*我基本上是想在不改变原始控制台应用程序的情况下将我的控制台应用程序变成一个 GUI 应用程序。

编辑:我尝试过的

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");
             }
          }); 

这就是我尝试写的,但它似乎不起作用。

【问题讨论】:

标签: java swing user-interface console-application actionlistener


【解决方案1】:

关于

我基本上是在尝试在不更改原始控制台应用程序的情况下将我的控制台应用程序变成一个 GUI 应用程序..."

我的建议很简单:“不要这样做”。

这两个应用程序具有完全不同的结构,一个是线性的,另一个是事件驱动的,并且不能直接相互转换。最好从头开始制作一个新的 GUI 程序。现在,如果您的非 GUI 应用程序包含一些结构良好且行为良好的面向对象类,那么请务必在您的 GUI 的“模型”或逻辑部分中使用这些类,但不要尝试直接翻译一种类型的程序流对对方的应用。

编辑
根据您发布的要求:

“您应该能够通过您的 GUI 界面玩您的 Battleship 游戏。此外,您为项目 1 编写的基于文本的前端应该仍然“工作”并且可以玩。”

如果我错了,请纠正我,但我敢打赌,这里涉及到几个类,其中只有一个是“基于文本的前端”。如果是这样,那么就像我上面建议的那样,使用非前端类作为你的 GUI 模型,但不要将基于文本的前端用于任何与 GUI 相关的东西,也不要尝试在你的 GUI 中模拟它。

【讨论】:

  • 不做我理解,我也比较习惯不做。但是在这种情况下,规范中规定我必须这样做。
  • “您应该可以通过您的 GUI 界面玩您的 Battleship 游戏。此外,您为项目 1 编写的基于文本的前端应该仍然“工作”并且可以玩。”跨度>
  • @user1043625:请参阅上面我的答案的更新。此外,考虑编辑您的个人资料并给自己一个不那么通用的论坛名称,希望比我的更好。 :)
  • 我确实有几个类,所有的输出都由一个类处理。但是,我们被告知将输入从 GUI 传递到控制台,而不是单独创建任何内容。
  • @user1043625:不,如果这些是您收到的说明,您没有被告知将输入从 GUI 传递到控制台。它所声明的只是通过 GUI 玩游戏,这意味着使用您可用的类,并且控制台游戏应该仍然可以玩。这意味着您不应该以使控制台界面无法播放的方式更改非控制台类。这是一个很大的区别。我仍然坚持我在回答中所说的内容。
【解决方案2】:

让控制台应用程序实例化按钮 ActionListener 并将其传递给 UI。当动作事件被触发时,监听器会告诉控制台应用它发生了。 ActionListener 中的方法会告诉它该做什么。

【讨论】:

  • 我不太明白,你能用一些简单的例子解释一下吗?另外,我认为这将修改我不应该做的原始类。
  • “不应该做” - 为什么不呢?
  • “您应该可以通过您的 GUI 界面玩您的 Battleship 游戏。此外,您为项目 1 编写的基于文本的前端应该仍然“工作”并且可以玩。”跨度>
  • 您的基于文本的 UI 和 GUI 用户界面需要分开。我认为您应该能够在两者之间进行选择。这将意味着对原作的修改。您的教授试图做的是让您将游戏逻辑与演示文稿完全分开。你的游戏逻辑应该通过它需要的东西。它不应该知道是文本还是 GUI UI 得到它。
【解决方案3】:

我同意 Hovercrafts 的评论(改为回复)。

但一般来说,对于这样的问题,我会更改你的 gameLoop() 的方法签名。我会使用:

public void gameLoop(Reader reader)

然后你可以根据需要将不同类型的阅读器传递给循环。

对于控制台,您可能会执行以下操作:

gameloop( new InputStreamReader( System.in ) );

对于 GUI,您可以执行以下操作:

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() );
    }
}

【讨论】:

  • 我在上面添加了一些内容来向您展示我尝试过的内容,但似乎对我不起作用。不知道我做错了什么。
  • @user1043625,我不明白你的评论。你为什么不试试我的建议,因为它的工作代码。我没有建议使用 PipedStream,所以我不知道你的代码有什么问题。
【解决方案4】:

如果你有这样的事情:

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

class A{

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

您可以在 A 中使用 final 声明对 B 的引用。在这种情况下,它将在内部类ActionListener 中可见。

class A{
  final B b = ...; //final variable is visible in inner class
  statsButton.addActionListener(new ActionListener() {
            b.gameLoop();
             ...
        }); 
}

【讨论】:

  • 我确实有一些与你写的类似的东西。但问题是当我单击按钮时如何更改 String cmd? b.gameLoop().cmd 不起作用,我认为我不应该这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
相关资源
最近更新 更多