Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 不知怎的,当我点击按钮执行方法调用时,我的GUI卡住了_Java_Multithreading_Swing_User Interface_Event Dispatch Thread - Fatal编程技术网

Java 不知怎的,当我点击按钮执行方法调用时,我的GUI卡住了

Java 不知怎的,当我点击按钮执行方法调用时,我的GUI卡住了,java,multithreading,swing,user-interface,event-dispatch-thread,Java,Multithreading,Swing,User Interface,Event Dispatch Thread,我想通过点击JButton更新电路板配置。但是,有时图像会显示在框架上。有时候不是。每次我点击按钮后都会有明显的延迟。我试着调试,发现在:EventDispatchThread.class中可能有一个无止境的循环 (this is the class from java library) void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) { addEventFilter(filter);

我想通过点击JButton更新电路板配置。但是,有时图像会显示在框架上。有时候不是。每次我点击按钮后都会有明显的延迟。我试着调试,发现在:EventDispatchThread.class中可能有一个无止境的循环

(this is the class from java library)
void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
    addEventFilter(filter);
    doDispatch = true;
while (doDispatch && cond.evaluate()) {
        if (isInterrupted() || !pumpOneEventForFilters(id)) {
            doDispatch = false;
        }
    }
    removeEventFilter(filter);
}
无止境的循环是上面的while循环

下面是我的listener类:

public class PlaceListener implements ActionListener{

private JTextField _text1;
private Board board;
private JTextField _text2;
private ArrayList<NewGUI> _guiList;
private int _numOfPlayer;
public PlaceListener(JTextField text1, JTextField text2, Board b,ArrayList<NewGUI> guiList, int numOfPlayer,NewGUI gui)
{
    _text1 = text1;
    _text2 = text2;
    board = b;
    _guiList = guiList;
    _numOfPlayer = numOfPlayer;
}
@Override
public void actionPerformed(ActionEvent e) {

    int x = Integer.parseInt(_text1.getText());
    int y = Integer.parseInt(_text2.getText());

    board.Place(y, x);

    for(int j = 0;j<_numOfPlayer;j++)
    {
          NewGUI gui = _guiList.get(j);
          gui.updateBoard();
          gui.updateCurrTile();
          gui.updateScore();
          gui.updateTurn();
    }
}
公共类PlaceListener实现ActionListener{
私有JTextField_text1;
私人董事会;
私有JTextField_text2;
私人律师事务所;
私人球员;
PublicPlaceListener(JTextField text1、JTextField text2、Board b、ArrayList guiList、int numOfPlayer、NewGUI)
{
_text1=text1;
_text2=text2;
董事会=b;
_guiList=guiList;
_numOfPlayer=numOfPlayer;
}
@凌驾
已执行的公共无效操作(操作事件e){
intx=Integer.parseInt(_text1.getText());
int y=Integer.parseInt(_text2.getText());
板。位置(y,x);

对于(int j=0;j,您的代码可能就是这里的问题所在。EventDispatchThread再次使用无休止的循环来处理事件,这是显而易见的,可以忽略为实际问题。您的问题来自于使用removeAll(),并在每次单击按钮时实例化数千个标签(13 x 13 x 89-65是多少?4056!)。这将导致大量不必要的重画和重新显示。因此,您看到的暂停是代码的性能,因为它效率不高。不要相信,请尝试以下方法:

public void updateBoard() {
    long start = System.currentTimeInMillis();

    // existing code goes here

    long duration = System.currentTimeMillis() - start;
    System.out.printf("UpdateBoard timing: %,d ms%n", duration );
}
如果你的代码超过10-100毫秒,你会觉得有问题。事实上,100毫秒是慢的,人类可以检测到100毫秒的延迟

您可能需要重新评估您的设计,或者重用现有标签,然后简单地调用setImage()来更改它们。毕竟,这就是使用持久化UI组件模型而不是使用原始绘制调用的全部意义。将它们实例化一次并重用

您还使用新的ImageIcon()调用创建了数千个图像。您可能只需要一个图标,并且所有标签都指向同一个图像,这也将大大减少内存使用量。事实上,如果您遵循我的建议,我想您会看到速度和内存的显著提高

如果找不到合适的方法来重用JLabor,那么可以考虑通过子类jbor或JPanel(如果您计划使用容器)并重写PrimtCuttoTeNe()来编写自己的组件。。我知道你没有使用布局管理器,而是选择使用绝对定位来完成所有操作。如果你要做绝对定位,你可能只想自己绘制。绘制是较低级别的界面,但你有完全的控制权。你必须自己处理定位、文字包装。但是,这将非常重要高效,并且可以从数据模型中重新绘制


由于您所做的一切都是以网格模式绘制图像,我认为使用Java2D api绘制图像比实例化那么多JLabel和ImageIcons要好。如果您将JPanel子类化,您可以向面板中添加JComponents,例如score等。但是,使用paintComponent()方法绘制网格。

什么是“线路板配置”?是EventDispatchThread.class您的类?您能显示执行此方法调用的JButton的ActionListener吗?好,这意味着
cond
始终为true,
isInterrupted()
始终为false,
pumpOneEventForFilters(id)
总是错误的。试着在循环中中断它,看看它是否有效。是的,当然在事件分派线程中有一个无止境的循环!这就是工作原理——在事件到达时以无止境的循环分派事件。您正在向我们展示Swing代码,那么您的代码呢?好的,我不确定,但请尝试重新绘制()在您的UI上。但我很确定错误不在Swing代码中。@Thomashrig我尝试重新绘制它,但它仍然拒绝在面板上显示标签…所有更新方法都有效,除了这个。我尝试计算时间结果如下:平铺放置在(1,1)中UpdateBoard计时:0毫秒UpdateBoard计时:0毫秒提交成功UpdateBoard计时:16毫秒UpdateBoard计时:0毫秒,因此问题不在于removeAll()。我有一个与电路板相反的类[][]数组,如果为空,则面板上不会放置任何内容。因此它不会生成那么多标签。我仍然不知道问题是什么…将计时代码包装在整个actionPerformed代码周围。如果您看到一个大跳跃,您可以将其隔离。请记住,updateBoard是为每个玩家调用的,因此有多个13*13*(89-65)*numberOfPlayers。这是一种潜力,当你的棋盘开始有更多的项目时,它会变得越来越慢。事实上,这比我们想象的更糟。+1
CellRenderPane
,可能会用作渲染器。
public void updateBoard() {
    long start = System.currentTimeInMillis();

    // existing code goes here

    long duration = System.currentTimeMillis() - start;
    System.out.printf("UpdateBoard timing: %,d ms%n", duration );
}