Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JTextArea文本消失_Java_Swing_Jtextarea - Fatal编程技术网

Java JTextArea文本消失

Java JTextArea文本消失,java,swing,jtextarea,Java,Swing,Jtextarea,我正在为一个项目制作一个国际象棋程序。我试图在黑板的侧面添加一个移动历史框。移动历史工作正常,数据被正确地发送到文本区域,但是当AI考虑他的移动时,JTextArea中的文本消失了 public void aiMove(){ if (!playing){ return; } paintImmediately(0,0,totalX,totalY); ai = eve.getMove(chess,wtm,aiOut); //text disappears here chess.m

我正在为一个项目制作一个国际象棋程序。我试图在黑板的侧面添加一个移动历史框。移动历史工作正常,数据被正确地发送到文本区域,但是当AI考虑他的移动时,JTextArea中的文本消失了

public void aiMove(){
  if (!playing){ return; }
  paintImmediately(0,0,totalX,totalY);
  ai = eve.getMove(chess,wtm,aiOut);   //text disappears here
  chess.makeMove(ai);
  wtm = !wtm;
  humanMove = true;
  writeMove(ai);                   //updates move history, text reappears here
  playing = stillPlaying();
  repaint();
}

private void writeMove(Move move){
  char c = "abcdefgh".charAt(7-move.fromY);
  char h ="abcdefgh".charAt(7-move.toY);
  String s = Character.toString(c)+(move.fromX+1)+" - "+Character.toString(h)+(move.toX+1)+"  ";
  if (!wtm){
    String q = chess.getFullMove()+".  "+s+"  ";
    moves.setText(moves.getText()+q);
  }
  else {
    moves.setText(moves.getText()+s+"\n");
  }
}
这是正在发生的事情的打印屏幕。


解决 感谢所有的回复。我更改了aiMove(),因此它创建了一个线程。这就是我所做的

尝试#3。。。秋千对我来说还是那么陌生。我不想将writeMove更改为getMove,否则我将不得不稍微重写人类的回合。由于项目基本上已经完成,我正在尽量避免做太多的工作:) 无论如何,GUI是完全可选的,我只是为了好玩,并尝试学习一些swing

public void aiMove(){
  if (!playing){ return; }
  if (!aiThread.isAlive()){
    aiThread = new Thread(){
      public void run(){
        ai = eve.getMove(chess,wtm,aiOut);
        chess.makeMove(ai);
        wtm = !wtm;
        humanMove = true;
        SwingUtilities.invokeLater(new Runnable(){
          public void run(){
            writeMove(ai);
          }
        });
        repaint();
        playing = stillPlaying();
      }
    };
    aiThread.start();
  }
}

它还修复了我以前遇到的一个问题,即如果我按下“a”键(强制ai移动),它将排队等待许多强制ai移动。现在这种情况没有发生。

问题是你的人工智能思维是CPU密集型/耗时型的,因此它被认为是一项长期运行的任务。您不应该在GUI事件调度线程上执行长时间运行的任务,因为这将导致UI看起来冻结,因此仅在任务完成后显示更新

幸运的是,您可以使用两种不同的方法:

  • 使用教程中所述的:
SwingWorker子类可以定义一个方法done,它是 在后台运行时在事件分派线程上自动调用 任务完成了

SwingWorker实现java.util.concurrent.Future。 此接口允许后台任务向提供返回值 另一根线。此接口中的其他方法允许取消 并发现后台任务是否具有 已完成或已取消

后台任务可以提供 通过调用SwingWorker.publish生成中间结果,导致 要从事件分派线程调用的SwingWorker.process

后台任务可以定义绑定属性。对这些文件的修改 属性触发事件,导致事件处理方法 在事件分派线程上调用

  • 或者为AI思维创建单独的
    线程
    ,并包装
    setText
    调用
    SwingUtilities.invokeLater(…)

更新

阅读MadProgrammers comment(+1)后,请记住通过
SwingUtilities.invokeLater(…)
块在EDT上创建/操作GUI/Swing组件。你可以阅读更多关于它的内容

更新2:

该编辑违背了这一点,在
swingutilites
块中对EDT的唯一调用应该是
setText
或至少只有操纵Swing组件的代码,即

public void aiMove(){
  if (!playing){ return; } 
  if (!aiThread.isAlive()){  //originally initialized by constructor
    aiThread = new Thread(){
      public void run(){
            ai = eve.getMove(chess,wtm,aiOut);
            chess.makeMove(ai);
            wtm = !wtm;
            humanMove = true;
        SwingUtilities.invokeLater(new Runnable(){
          public void run(){
            writeMove(ai);
          }
        });
        repaint();
        playing = stillPlaying();
      }
    };
    aiThread.start();
  }
}

在单独的线程中运行耗时的任务将避免GUI冻结。我不确定是否发生了这种情况,但您应该仅将主线程用于GUI操作,因为此线程将刷新GUI。业务逻辑(特别是如果需要一段时间才能完成)应该在一个单独的线程中。您更新的代码违反了线程规则Swing-除了事件调度线程之外,您不能从任何线程更新任何UI元素-查看David的回答,因为他提供了关于如何修复这些问题的重要指点problems@twentylemon很抱歉,确实不需要getMove更新。所以我把它删掉了。我看到你更新了你的代码,所以它一定还在出问题?确保在edt上创建jframe和其他组件,这通常可以通过在SwingUtilities.invokeXXX块中包装对创建jframe的调用来解决。如果SSCCENo后仍不起作用,则问题已解决。我为其他和我有同样问题的人更新了它。谢谢您的帮助。@twentylemon很高兴它能工作……如果这是答案,请勾选此帖子旁边的复选标记,将其显示为答案并已解决。
public void aiMove(){
  if (!playing){ return; } 
  if (!aiThread.isAlive()){  //originally initialized by constructor
    aiThread = new Thread(){
      public void run(){
            ai = eve.getMove(chess,wtm,aiOut);
            chess.makeMove(ai);
            wtm = !wtm;
            humanMove = true;
        SwingUtilities.invokeLater(new Runnable(){
          public void run(){
            writeMove(ai);
          }
        });
        repaint();
        playing = stillPlaying();
      }
    };
    aiThread.start();
  }
}