Java 用绘画方法穿线

Java 用绘画方法穿线,java,multithreading,swing,paintcomponent,event-dispatch-thread,Java,Multithreading,Swing,Paintcomponent,Event Dispatch Thread,我想知道如何执行以下代码,或者只是一个方法: 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); } } } 公

我想知道如何执行以下代码,或者只是一个方法:

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);
        }
    }
}
公共作废运行(){
公共空间涂料(图g){
g、 fillRect(20,20,20,20);
对于(int i=20;i<1000;i++){
g、 fillRect(20,i,20,20);
睡眠(10);
}
}
}

我发现我无法创建此代码的线程,因为我得到了表达式错误的非法开始,这是公平的,但我看不到解决方法。

很难判断您在做什么

但似乎您正试图从
run()
方法中重写
Runnable
paint()

这当然不能做到

逻辑是

  • 拿一个部件
  • 覆盖其绘制方法以绘制所需内容
  • 调用方法来更新矩形的坐标(或者在这种情况下,计时器将这样做)
  • 然后在组件上调用
    repaint()
    ,这样就可以再次调用paint方法,并用新坐标重新绘制矩形(更改矩形坐标后,计时器还将负责重新绘制)
  • 根据需要/需要重复最后2步
(当我说组件时,我实际上是指
JPanel
,paint方法指的是
JPanel
的重写
paintComponent(..)
,因为这是最佳实践。)

一些建议:

1) 不要覆盖
paint
而是使用
JPanel
和覆盖
paintComponent

2) 不要忘记遵守绘制链,并调用重写的
paintComponent(Graphics g)
(或该事实的任何重写方法)的
super.XXX
实现,除非故意将其忽略。i、 e

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

         //do drawings here
    }
}
3) 如果在
paintComponent
中绘图,通常需要覆盖
getPreferredSize()
并返回符合
JPanel
内容/图纸的
尺寸,即:

class MyPanel extends JPanel {
    @Override
    public Dimension getPreferredSize() {
         return new Dimension(300,300);
    }
}
3) 查看而不是
Thread.sleep(..)
因为
sleep
将阻塞GUI线程并使其看起来被冻结。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();

不允许在Gui线程之外进行绘制。您不能将绘图重定向到辅助线程。@NickHaughton也看到了类似的答案,它使用一个摆动计时器移动球,然后重新绘制其容器以重新选择更改:
    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