穿线油漆方法

时间:2012-12-28 16:56:28

标签: java multithreading swing paint 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);
        }
    }
}

我发现我无法创建此代码的线程,因为我得到了一个非法的表达式错误启动,这是公平的,但我没有看到解决方法。

1 个答案:

答案 0 :(得分:13)

很难说出你在做什么,

但似乎您试图在其paint()方法中覆盖Runnable的{​​{1}}。

肯定不会这样做。

逻辑是

  • 拿一个组件
  • 覆盖其绘制方法以绘制我们需要的内容
  • 更新矩形坐标的调用方法(或者在这种情况下,计时器会这样做)
  • 在组件上调用run(),因此可以再次调用paint方法并使用新的坐标重绘矩形(Timer也会在更改Rectangle的坐标后重新绘制)
  • 根据需要/想要重复最后两个步骤

(当我说组件我实际上是指repaint()时, paint方法指的是JPanel被覆盖的paintComponent(..),因为这是最佳实践。)

一些建议:

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

2)不要忘记尊重 paint chain 并调用paintComponent实现重写的super.XXX(或任何被覆盖的方法),除非故意将其删除。即

paintComponent(Graphics g)

3)如果在class MyPanel extends JPanel { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); //do drawings here } } 中绘图,通常需要覆盖paintComponent并返回符合getPreferredSize()的内容/图纸的Dimension,即:

JPanel

3)查看Swing Timer而不是class MyPanel extends JPanel { @Override public Dimension getPreferredSize() { return new Dimension(300,300); } } ,因为Thread.sleep(..)将阻止GUI线程,并使其似乎被冻结。即

sleep

4)另一种选择(因为我现在看到你只是将一个不是Swing组件的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(); 移动到Swing计时器是TimerTask,只要没有Swing就可以使用它组件将在其Rectangle方法中创建/操作(因为run()不能像在Swing Timer上那样在EDT上运行)。注意TimerTaskrevalidate() 线程安全,因此可以在repaint()内使用。

上述优点是EDT保留了不必要的代码(即通过改变co-ords来移动AWT矩形),即

TimerTask