我想知道如何编写以下代码,或者只是一个方法:
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);
}
}
}
我发现我无法创建此代码的线程,因为我得到了一个非法的表达式错误启动,这是公平的,但我没有看到解决方法。
答案 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上运行)。注意TimerTask
和revalidate()
线程安全,因此可以在repaint()
内使用。
上述优点是EDT保留了不必要的代码(即通过改变co-ords来移动AWT矩形),即
TimerTask