0

我使用 TimerTask 在我的一个类的循环上添加了一个计时器,该类由绘画组件类调用。基本上在已经绘制的页面上有白色圆圈,然后有一个 for 循环,它从数组中读取一个值,并且根据值的范围,圆圈会改变颜色。每个圆圈应该代表数组中的下一个值。但它不工作。我是一个基本的程序员,真的不明白出了什么问题。如果有人能帮帮我,我将不胜感激。到目前为止,这是我的代码:

public DoThePaint() {



    String fileName;
    fileName = "/Users/Desktop/test2.txt";
    read = new Reader(fileName);
    read.displayArrayList();

    panel = new JPanel();
    newImage = new ImageIcon(this.getClass().getResource("resource/background2T.png")).getImage();

    circlesT = new ArrayList<Shape>();
    circlesT.add(new Ellipse2D.Float(197.0f, 352.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(247.0f, 307.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(152.0f, 303.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(172.0f, 372.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(223.0f, 378.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(273.0f, 285.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(130.0f, 281.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(148.0f, 393.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(246.0f, 403.0f, 10.0f, 10.0f));
    circlesT.add(new Ellipse2D.Float(297.0f, 264.0f, 10.0f, 10.0f));
}
public void paintComponent(Graphics g) {

    drawShapes(g, circlesT);

}

public void drawShapes(Graphics g, final ArrayList<Shape> circlesT) {
    final Graphics2D ga = (Graphics2D) g;
    ga.drawImage(newImage, 0, 0, null);



    for (int i = 0; i < circlesT.size(); i++) {
        ga.draw(circlesT.get(i));
        ga.setPaint(Color.white);
        ga.fill(circlesT.get(i));
    }



    Timer timer = new Timer();
    TimerTask t;
    t = new TimerTask() {
        @Override
        public void run() {

            for (int i = 0; i < 10; i++) {


                if (read.temp.get(i) < 31 && read.temp.get(i) > 30) {
                    ga.draw(circlesT.get(i));
                    ga.setPaint(Color.green);
                    ga.fill(circlesT.get(i));
                } else if (read.temp.get(i) < 32 && read.temp.get(i) > 31) {
                    ga.draw(circlesT.get(i));
                    ga.setPaint(Color.red);
                    ga.fill(circlesT.get(i));
                } else if (read.temp.get(i) < 33 && read.temp.get(i) > 32) {
                    ga.draw(circlesT.get(i));
                    ga.setPaint(Color.yellow);
                    ga.fill(circlesT.get(i));
                }

            }
        }
    };
    repaint();
    timer.schedule(t, 0, 5000);

}
4

2 回答 2

4

对不起,但这是你制造的恐怖大厅:在paintComponent()你的内部正在创造 a new Timer, anew TimerTask并最终呼唤repaint()

  1. paintComponent(): 你应该做的就是绘画操作(画图、画圆、画线、画文字……在上面Graphics)。这就是你应该做的。
  2. 调用repaint()最终将触发paintComponent()再次调用--> 重新创建计时器、计时器任务并调用 repaint()-->paintComponent()->repaint()-->... 你明白了,你刚刚创建了一个无限循环消耗你的资源
  3. 我不知道你的Reader班级做什么以及它拥有什么数据。我可以看到两件我会改变的事情:temp应该private使用 getter 或其他访问方法正确访问。您在循环中的条件非常严格,您确定所有值都将匹配 3 个条件之一(顺便说一句,您的条件都是falseifread.temp.get(i)返回一个intor Integer)。
  4. 要解决所有这些问题,请删除 Timer,删除 TimerTask 并在您的第一次for-loop查找中直接查找圆圈的颜色并立即正确绘制它们。如果在某个时候,您想更新显示,那么您可以调用repaint()
  5. 顺便说一句,您TimerTask没有在 EDT(事件调度线程)上运行,但您仍然可以从其中访问与 UI 相关的内容。这违反了所有与 UI 相关的任务都应在 EDT 上执行的事实(使用 SwingTimerSwingUtilities.invokeLater()
  6. 在您的TimerTask访问中,与提供Graphics2D ga的相同:您不能在方法范围之外访问该对象。已创建和处置,因此不应在其范围之外使用。一般来说,您永远不应该保留对对象的引用(也不应该使用可能很诱人但会导致各种令人头疼的方法)。Graphics gpaintComponent()GraphicspaintComponentGraphicsGraphicsgetGraphics()
于 2013-02-26T13:42:46.283 回答
1

您对绘画在 Swing 中的工作方式存在根本性的误解。不过没什么大不了的,每个人都必须从某个地方开始。

看起来你想做动画。因此,您的paintComponent 方法应该在特定时间点绘制对象的状态。任何控制绘制时间的计时器都应该属于另一个类。

对于简单的动画 TimerTask 就可以了。如果您想要为游戏制作动画或某些需要良好性能的东西,我推荐 Andrew Davison 所著的 Killer Game Programming in Java 一书第 2 章中的动画类。您实际上可以在亚马逊的 Look Inside 功能中阅读第 2 章。

于 2013-02-26T14:14:13.063 回答