java - 使用 for 循环将多个 Jlabel 添加到 Jframe,删除它们并将它们打印在新位置

标签 java swing

我目前正在用 java 创建 Flappy Bird 克隆,但在重新打印管道时遇到问题。我的意思是,在 while 循环中,我在右侧打印管道图像,然后打印旧管道(如果有)(在第一个循环中没有任何管道)。然后将第一个管道的 X 和 Y 坐标添加到两个单独的列表(用于存储管道坐标),然后我使用 for 循环更改列表中的所有 x 坐标,并留下 50 个像素。下一步是转到循环的顶部并删除所有管道并重新开始。问题是我无法删除使用 for 循环添加的所有管道。这是我使用的 while 循环中的代码(有两个词 frame.remove(pipeOld); 不是删除所有旧管道,而是删除第一个管道。):

        while (true) {

        frameCounter++;
        int curentFrame = animationFrame;
        animationFrame = calculateAnimationFrame(curentFrame);

        frame.remove(pipe);
        frame.remove(pipeOld); 

        pipeY = rnd.nextInt(100); //declared already
        pipe = showPipes(pipeX,pipeY,animationFrame); // method

        frame.add(pipe); // printing pipe

        for (int i = 0; i < pipeListX.size(); i++) {            
            pipeOld = showPipes(pipeListX.get(i),pipeListY.get(i),animationFrame);
            frame.add(pipeOld);             
        }

        pipeListX.add(pipeX); // adding current pipe X to list
        pipeListY.add(pipeY); // adding current pipe y to list

        for (int i = 0; i < pipeListX.size(); i++) { // declaring new x for all the pipes, so they can move
            int pipeNew = pipeListX.get(i);
            pipeListX.set(i, pipeNew - 50);
        }


        frame.validate(); // Validates the window

        frame.repaint(); // Repaints the window

        Thread.sleep(15); // Game speed setting
    }

最佳答案

以下来自metaSO的建议:

回答您的特定问题
pipeOld 仅存储最后一个管道。您在 for 循环中覆盖它,因此它只包含最后添加的管道,因此这就是在下一个循环迭代中被删除的内容。如果要跟踪所有旧管道,则应该使用集合而不是单个管道引用,并在循环中删除所有旧管道。

for (JComponent pipe : oldPipes) {
    frame.remove(pipe);
}
oldPipes.clear();

<other code>

for (int i = 0; i < pipeListX.size(); i++) {            
    pipeOld = showPipes(pipeListX.get(i), pipeListY.get(i), animationFrame);
    frame.add(pipeOld);             
    oldPipes.add(pipeOld);
}

但是您根本不应该这样做!
在循环中添加和删除组件以及在 EDT 中使用 Thread.sleep 都是极其糟糕的做法!

  • 正如评论中已经提到的,在 EDT 中使用 Thread.sleep 将意味着 GUI 卡住和无响应。 Andrew Thompson 说 TimerSwingWorker 对此要好得多,这是完全正确的。我将在这里重新发布他的链接,以免丢失:Concurrency in Swing 。您还应该考虑切换到 MVC 架构,以便您的游戏速度不受帧速率的影响。
  • 添加和删除组件是非常昂贵的操作!每次执行此操作时,父组件都会完全重新计算其布局。大多数实时游戏(因此具有移动对象并需要一致的帧速率)使用 Canvas 进行自定义绘画。

关于java - 使用 for 循环将多个 Jlabel 添加到 Jframe,删除它们并将它们打印在新位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23757050/

相关文章:

java - Swing 中的 JDialog 中的单选按钮?

java - findViewWithTag 在循环内部使用时给出空对象引用

java - 如何设置 JTextField 的大小(以像素为单位)

java - 如何在JSP循环中访问两个类的变量

JAVA Telegram bots api 获取更新时出错 : Conflict: terminated by other long poll or webhook

Java - 如何在 JTextArea 中拆分整个单词

java - 如何让 Java 托盘图标消息淡出?

java - 调整元素的大小和位置

java - 如何将src文件添加到jar中?

java - 从Java中的单独类文件调用方法