繁体   English   中英

TImerTask在paintComponent上

[英]TImerTask on paintComponent

我已经使用TimerTask在我的一个类的循环上添加了一个计时器,该循环由paint组件类调用。 基本上,页面上已经绘制了白色圆圈,然后有一个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);

}

抱歉,但这是您造成的恐惧:在paintComponent()您将创建一个new Timer ,一个new TimerTask并最终调用repaint()

  1. paintComponent() :您要做的只是绘画操作(在Graphics上绘制图像,填充圆,绘制线,绘制文本,...)。 那就是你应该做的。
  2. 调用repaint()最终将触发paintComponent()再次被调用->重新创建计时器,计时器任务并调用repaint()-> paintComponent()-> repaint()-> ... ,您刚刚创建了一个无限循环,耗尽了您的资源
  3. 我不知道您的Reader类做什么以及它拥有什么数据。 我可以看到有两点需要更改: temp应该是private并且可以使用getter或其他某种访问方法正确地进行访问。 循环中的条件非常严格,您确定所有值都将匹配3个条件之一(顺便说一句,如果read.temp.get(i)返回intInteger ,则条件均为false )。
  4. 要解决所有这些问题,请放下Timer,放下TimerTask,并在您的第一个for-loop查找中直接添加圆圈的颜色,并立即正确绘制它们。 如果要更新显示,则可以调用repaint()
  5. 顺便说一句,您的TimerTask不在EDT(事件调度线程)上运行,但是您仍然可以从其中访问与UI相关的内容。 这违反了所有与UI相关的任务都应在EDT上执行的事实(使用Swing TimerSwingUtilities.invokeLater() )。
  6. TimerTask您可以访问Graphics2D ga ,它与paintComponent()提供的Graphics g相同:您不能在paintComponent方法的范围之外访问该Graphics对象。 Graphics是创建和处理的,因此不应在其范围之外使用。 通常,您永远不应保留对Graphics对象的引用(也不要使用getGraphics()方法,该方法可能很吸引人,但会引起各种严重的麻烦)。

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

您似乎想制作动画。 因此,您的paintComponent方法应该在特定的时间点绘制对象的状态。 任何控制油漆时间的计时器都应该属于另一类。

对于简单的动画,TimerTask很好。 如果您想制作游戏动画或需要良好性能的游戏,我建议安德鲁·戴维森(Andrew Davison)在《 Killer Game Programming in Java》一书的第2章中介绍动画类。 您实际上可以在Amazon的Look Inside功能中阅读第2章。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM