穿线绘画方法 [英] Threading a paint method
问题描述
我想知道如何处理以下代码,或者只是一种方法:
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方法,并使用其新坐标重新绘制矩形(在更改Rectangle坐标后,Timer还将负责重新绘制) - 根据需要/需要将最后2步重复多次
(当我说 component 时,我实际上是指JPanel
, paint方法指的是JPanel
的覆盖的paintComponent(..)
,因为这是最佳做法.)>
一些建议:
1)不要覆盖paint
,而要使用JPanel
并覆盖paintComponent
.
2)不要忘记遵守 paint链并调用覆盖的paintComponent(Graphics g)
(或任何事实的覆盖方法)的super.XXX
实现,除非有意地将其遗漏了.即
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
替换为sleep
,而不是Thread.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计时器中)是 解决方案
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
- Take a component
- Override its paint method to draw what we need
- Call method to update co-ordinates of rectangle (or in this case timer will do that)
- Than call
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) - repeat last 2 steps as many times as needed/wanted
(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
这篇关于穿线绘画方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!