我需要提示如何使我的程序正常工作。我创建了一个从JComponent扩展的类。我还设法制作了整个白色面板。现在我试图让我的线程Wolf将被绘制在JCOmponent上并将移动一次。不幸的是我的代码不起作用,我认为它是因为狼没有被涂在白板上。如何更改程序以使其工作。我将不胜感激。
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) {
}
}
答案 0 :(得分:4)
首先来看看Performing Custom Painting和Painting in AWT and Swing,了解有关如何在Swing中执行绘画的详细信息。
请查看Concurrency in Swing,了解有关处理Swing线程的详细信息。
基本上,只会绘制显示容器上的组件。这意味着只会对您的Plansza
进行绘制,但只有当它被添加到(直接或其他)JFrame
之类的内容时才会被绘制,并且JFrame
可见。
这意味着Wilk
永远不会被绘制,因此它的paintComponent
方法变得毫无意义(在此上下文中)
您可以使用的方法是将您想要绘制的内容从Wilk
(控制器)传达到Plansza
(视图)。这通常通过使用某种模型来实现,该模型允许控制器更改其状态和视图以呈现该状态。
例如......
这是Model-Control-View实施的基本演示。
模型驱动视图,控制器驱动模型。这样,只要满足模型的契约,各种元素就彼此独立
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class PaintModel {
public static void main(String[] args) {
new PaintModel();
}
public PaintModel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
MutableModel model = new DefaultModel();
Controller controller = new Controller(model);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new View(model));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
controller.start();
}
});
}
public interface Model {
public Rectangle getBounds();
public Dimension getSize();
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
public interface MutableModel extends Model {
public void update();
}
public class DefaultModel implements MutableModel {
private final Dimension size = new Dimension(200, 200);
private final Rectangle bounds = new Rectangle(95, 95, 10, 10);
private int xDelta = ((int) (Math.random() * 5)) + 1;
private int yDelta = ((int) (Math.random() * 5)) + 1;
private List<ChangeListener> changeListeners;
public DefaultModel() {
changeListeners = new ArrayList<>(25);
}
@Override
public void addChangeListener(ChangeListener listener) {
changeListeners.add(listener);
}
@Override
public void removeChangeListener(ChangeListener listener) {
changeListeners.remove(listener);
}
protected void fireStateChanged() {
if (changeListeners.size() > 0) {
ChangeEvent evt = new ChangeEvent(this);
Iterator<ChangeListener> it = changeListeners.iterator();
while (it.hasNext()) {
ChangeListener listener = it.next();
listener.stateChanged(evt);
}
}
}
@Override
public Dimension getSize() {
return size;
}
@Override
public Rectangle getBounds() {
return bounds;
}
@Override
public void update() {
bounds.x += xDelta;
bounds.y += yDelta;
if (bounds.x < 0) {
bounds.x = 0;
xDelta *= -1;
} else if (bounds.x + bounds.width > size.width) {
bounds.x = size.width - bounds.width;
xDelta *= -1;
}
if (bounds.y < 0) {
bounds.y = 0;
yDelta *= -1;
} else if (bounds.y + bounds.height > size.height) {
bounds.y = size.height - bounds.height;
yDelta *= -1;
}
fireStateChanged();
}
}
public class Controller extends Thread {
private MutableModel model;
public Controller(MutableModel model) {
this.model = model;
setDaemon(true);
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(40);
} catch (InterruptedException ex) {
}
model.update();
}
}
}
public class View extends JComponent implements ChangeListener {
private Model model;
public View(Model model) {
this.model = model;
this.model.addChangeListener(this);
setBackground(Color.WHITE);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(model.getSize());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
Rectangle bounds = model.getBounds();
g2d.setColor(Color.BLUE);
g2d.drawOval(bounds.x, bounds.y, bounds.width, bounds.height);
g2d.dispose();
}
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
}
}
答案 1 :(得分:1)
在许多现代语言中,UI在主线程上运行,你不能从另一个线程修改它(或者你不应该至少)。 (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html)
虽然repaint()和revalidate()是线程安全的,并且它们有自己的invokeAndWait,但你必须使用类似的东西创建UI。
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createGUI();
}
});
因此,每次绘制主面板时都会创建一个油漆狼纹。
Oracle也建议在http://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html
中致电super.paintComponent(g);
我建议您完全阅读Oracle Swing指南,然后尝试修改Flipper硬币示例以便按照您的需要工作(http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/concurrency/FlipperProject/src/concurrency/Flipper.java)