Трудно сказать, что ты делаешь,
но похоже, что вы пытаетесь переопределить paint()
из Runnable
из его метода run()
.
Этого точно нельзя делать.
Логика
- Возьмите компонент
- Переопределите его метод рисования, чтобы нарисовать то, что нам нужно
- Метод вызова для обновления координат прямоугольника (или в этом случае это сделает таймер)
- Затем вызовите
repaint()
для компонента, чтобы метод рисования можно было вызвать снова и перерисовать прямоугольник с его новыми координатами (таймер также позаботится о перерисовке после изменения координат прямоугольника).
- повторите последние 2 шага столько раз, сколько необходимо / хотите
(когда я говорю компонент, я на самом деле имею в виду JPanel
, метод рисования относится к переопределенному paintComponent(..)
из JPanel
, так как это лучшая практика.)
Некоторые предложения:
1) Не переопределяйте paint
, а используйте JPanel
и переопределяйте paintComponent
.
2) Не забудьте соблюдать цепочку рисования и вызвать super.XXX
реализацию переопределенного paintComponent(Graphics g)
(или любой переопределенный метод для этого факта), если только это не было преднамеренно исключено. то есть
class MyPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//do drawings here
}
}
3) При рисовании в paintComponent
обычно необходимо переопределить getPreferredSize()
и вернуть Dimension
s, которые соответствуют содержимому/рисункам JPanel
, т.е.:
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) Альтернатива (потому что я вижу, что вы перемещаете только Rectangle
, который не является компонентом Swing) на таймер Swing: TimerTask
, и это можно использовать до тех пор, пока никакие компоненты Swing не будут создаваться/управляться из его метода run()
(поскольку TimerTask
не работает в EDT, как Swing Timer). Примечание. revalidate()
и repaint()
являются потокобезопасными, поэтому их можно использовать в TimerTask
.
Преимущество вышеизложенного заключается в том, что ненужный код сохраняется в EDT (т.е. перемещение прямоугольника 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
person
David Kroukamp
schedule
28.12.2012