穿线油漆方法
我想知道如何编写以下代码,或者只是一个方法:
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()
方法中覆盖Runnable
paint()
。
肯定不会这样做。
逻辑是
- 拿一个组件
- 覆盖其绘制方法以绘制我们需要的内容
- 调用方法来更新矩形的坐标(或者在这种情况下,计时器会这样做)
- 比调用组件上的
repaint()
所以可以再次调用paint方法并用新的坐标重绘矩形(Timer也会在更改Rectangle的坐标后重新绘制) - 根据需要/需要重复最后两个步骤
(当我说组件我实际上是指JPanel
, paint方法指的是JPanel
重写paintComponent(..)
,因为这是最佳实践。)
一些建议:
1)不要覆盖paint
而是使用JPanel
并覆盖paintComponent
。
2)不要忘记尊重paint链并调用super.XXX
实现重写的paintComponent(Graphics g)
(或任何被覆盖的方法),除非故意将其删除。 即
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
而不是Thread.sleep(..)
因为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定时器)是TimerTask
,只要在其run()
没有创建/操作Swing组件,就可以使用它run()
方法(因为TimerTask
不像Swing Timer那样在EDT上运行)。 注意revalidate()
和repaint()
是线程安全的,因此它可以在TimerTask
。
上述优点是EDT保持不必要的代码(即通过改变co-ords来移动AWT矩形)即
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