I was wondering how I would thread the following code, or just a method in general:
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);
}
}
}
I find that I am unable to make a thread of this code because I get an illegal start of expression error, which is fair but I do not see a way around it.
Its hard to tell what you are doing,
but seems like you are trying to override paint()
of a Runnable
from within its run()
method.
This can surely not be done.
The logic is
repaint()
on the component so paint method may be called again and redraw the rectangle with its new co-ordinates (Timer would also take care of repainting after changing co-ordinates of Rectangle)(when I say component I actually mean JPanel
, paint method refers to overridden paintComponent(..)
of JPanel
as this is best practice.)
Some suggestions:
1) Dont override paint
rather use JPanel
and override paintComponent
.
2) Dont forget to honor the paint chain and call super.XXX
implementation of overridden paintComponent(Graphics g)
(or any overridden method for that fact) unless purposefully leaving it out. i.e
class MyPanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//do drawings here
}
}
3) If drawing in paintComponent
it is usually needed to override getPreferredSize()
and return Dimension
s which fit the contents/drawings of JPanel
, i.e:
class MyPanel extends JPanel {
@Override
public Dimension getPreferredSize() {
return new Dimension(300,300);
}
}
3) Look at Swing Timer
instead of Thread.sleep(..)
as sleep
will block GUI thread and make it seem to be frozen. 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();
4) An alternative (because I see for now you are only moving a Rectangle
which is not a Swing component) to Swing timer is TimerTask
, and this can be used as long as no Swing components will be created/manipulated from within its run()
method (as TimerTask
does not run on EDT like Swing Timer). Note revalidate()
and repaint()
are Thread-safe so it can be used within TimerTask
.
The advantage of the above is unnecessary code is kept of EDT (i.e moving AWT rectangle by changing co-ords) i.e
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With