穿线绘画方法 [英] Threading a paint method

查看:163
本文介绍了穿线绘画方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何处理以下代码,或者只是一种方法:

public void run (){

    public void paint(Graphics g) {
        g.fillRect(20, 20, 20, 20);
        for (int i = 20; i < 1000; i++) {
            g.fillRect(20, i, 20, 20);
            Thread.sleep(10);
        }
    }
}

我发现我无法编写此代码的线程,因为出现了非法的表达式错误开始,这很公平,但是我看不到解决方法.

解决方案

很难分辨你在做什么,

,但似乎您正在尝试从其run()方法中覆盖Runnablepaint().

这肯定是做不到的.

逻辑是

  • 接受组件
  • 重写其绘制方法以绘制所需的内容
  • 调用方法以更新矩形的坐标(在这种情况下,计时器将执行此操作)
  • 要在组件上调用repaint(),以便可以再次调用paint方法,并使用其新坐标重新绘制矩形(在更改Rectangle坐标后,Timer还将负责重新绘制)
  • 根据需要/需要将最后2步重复多次

(当我说 component 时,我实际上是指JPanel paint方法指的是JPanel的覆盖的paintComponent(..),因为这是最佳做法.)

一些建议:

1)不要覆盖paint,而要使用JPanel并覆盖paintComponent.

2)不要忘记遵守 paint链并调用覆盖的paintComponent(Graphics g)(或任何事实的覆盖方法)的super.XXX实现,除非有意地将其遗漏了.即

class MyPanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

         //do drawings here
    }
}

3)如果使用paintComponent进行绘制,通常需要覆盖getPreferredSize()并返回与JPanel的内容/图形相符的Dimension,即:

class MyPanel extends JPanel {
    @Override
    public Dimension getPreferredSize() {
         return new Dimension(300,300);
    }
}

3)将 Swing Timer 替换为sleep,而不是Thread.sleep(..) >将阻止GUI线程,并使其似乎被冻结.即

Timer t = new Timer(10, new AbstractAction() {
    int count = 20;
    @Override
    public void actionPerformed(ActionEvent ae) {
        if (count < 1000) {
            //increment rectangles y position
            //now repaint container so we can see changes in co-ordinates (unless you have a timer which repaints for you too)
            count++;
        } else {//counter is at 1000 stop the timer
            ((Timer) ae.getSource()).stop();
        }
    }
});
t.start();

4)另一种方法(因为我现在看到的是,您仅将不是Swing组件的Rectangle移到了Swing计时器中)是 解决方案

Its hard to tell what you are doing,

but seems like you are trying to override paint() of a Runnable from within its run() method.

This can surely not be done.

The logic is

  • Take a component
  • Override its paint method to draw what we need
  • Call method to update co-ordinates of rectangle (or in this case timer will do that)
  • Than call repaint() on the component so paint method may be called again and redraw the rectangle with its new co-ordinates (Timer would also take care of repainting after changing co-ordinates of Rectangle)
  • repeat last 2 steps as many times as needed/wanted

(when I say component I actually mean JPanel, paint method refers to overridden paintComponent(..) of JPanel as this is best practice.)

Some suggestions:

1) Dont override paint rather use JPanel and override paintComponent.

2) Dont forget to honor the paint chain and call super.XXX implementation of overridden paintComponent(Graphics g) (or any overridden method for that fact) unless purposefully leaving it out. i.e

class MyPanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

         //do drawings here
    }
}

3) If drawing in paintComponent it is usually needed to override getPreferredSize() and return Dimensions which fit the contents/drawings of JPanel, i.e:

class MyPanel extends JPanel {
    @Override
    public Dimension getPreferredSize() {
         return new Dimension(300,300);
    }
}

3) Look at Swing Timer instead of Thread.sleep(..) as sleep will block GUI thread and make it seem to be frozen. i.e

Timer t = new Timer(10, new AbstractAction() {
    int count = 20;
    @Override
    public void actionPerformed(ActionEvent ae) {
        if (count < 1000) {
            //increment rectangles y position
            //now repaint container so we can see changes in co-ordinates (unless you have a timer which repaints for you too)
            count++;
        } else {//counter is at 1000 stop the timer
            ((Timer) ae.getSource()).stop();
        }
    }
});
t.start();

4) An alternative (because I see for now you are only moving a Rectangle which is not a Swing component) to Swing timer is TimerTask, and this can be used as long as no Swing components will be created/manipulated from within its run() method (as TimerTask does not run on EDT like Swing Timer). Note revalidate() and repaint() are Thread-safe so it can be used within TimerTask.

The advantage of the above is unnecessary code is kept of EDT (i.e moving AWT rectangle by changing co-ords) i.e

    final TimerTask tt = new TimerTask() {
        @Override
        public void run() {
            if (count < 1000) {
               //increment rectangles y position
                //now repaint container so we can see changes in co-ordinates (unless you have a timer which repaints for you too)
            count++;
            } else {//counter is at 1000 stop the timer
                cancel();
            }
        }
    };

    new Timer().scheduleAtFixedRate(tt, 0, 10);//start in 0milis and call run every 10 milis

这篇关于穿线绘画方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆