多线程Java线程和图形2D
我需要一个如何使我的程序正常工作的提示。我创建了一个从JComponent扩展而来的类。我还把整个面板做成了白色。现在我想让我的线程Wolf被画在JC组件上,并移动一次。不幸的是,我的代码不起作用,我认为这是因为wolf没有被画在白板上。如何更改程序以使其工作。我将非常感激你的帮助
public class Plansza extends JComponent implements ActionListener {
static int width = 500;
static int height = 500;
Ellipse2D wolf;
Ellipse2D hare;
// size of frame n x m (width,height)
public Dimension getPreferredSize(){
return new Dimension(width,height);
}
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
//draw a background
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
}
class Wilk implements Runnable{
private int x;
private int y;
//when creating a thread we get a first position of wolf
Wilk(int posx, int posy){
x=posx;
y=posy;
}
protected void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
//draw a wolf
g.setColor(Color.BLUE);
wolf = new Ellipse2D.Double(x,y, 10, 10);
g2.fill(wolf);
}
public void run() {
x=x+5;
y=y+5;
repaint();
}
}
public static void main( final String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame window = new JFrame("Wilki vs Zajace");
Plansza p = new Plansza();
window.add(p);
window.pack();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setVisible(true);
// Timer t = new Timer(10,p); //action listener referred to Plansza(1 cycle every 100miliseconds)
// t.start();
Wilk wolf = new Wilk(10,10);
Thread myWolf = new Thread(wolf);
myWolf.start();
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
# 1 楼答案
从看Performing Custom Painting和Painting in AWT and Swing开始,了解Swing中如何进行绘画的细节
查看Concurrency in Swing了解有关处理Swing a线程的详细信息
基本上,只会在展示的容器上绘制一个组件。这意味着只有你的
Plansza
会被绘制,但只有当它被添加到一个类似JFrame
的东西中,并且JFrame
才是可见的这意味着
Wilk
永远无法绘制,因此它的paintComponent
方法变得有些毫无意义(在本文中)您可以使用某种方式将您想要绘制的内容从
Wilk
(控制器)传达到Plansza
(视图)。这通常是通过使用某种模型来实现的,该模型允许控制器更改其状态,并允许视图渲染该状态例如
这是Model-Control-View实现的基本演示
模型驱动视图,控制器驱动模型。这样,只要满足模型的契约,各个元素就相互独立
# 2 楼答案
在许多现代语言中,UI在主线程上运行,您不能从另一个线程修改它(或者至少不应该)。(http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html)
尽管repaint()和revalidate()是线程安全的,并且它们有自己的invokeAndWait,但您必须使用类似的方式创建UI
因此,每次绘制主面板时,都会创建一条绘制狼线
甲骨文还建议在http://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html中调用
super.paintComponent(g);
我建议您完全阅读《Oracle Swing指南》,然后尝试修改Flipper coin示例,使其能够按照您的需要工作(http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/concurrency/FlipperProject/src/concurrency/Flipper.java)