Java线程和图形2D

Java线程和图形2D,java,multithreading,swing,user-interface,paintcomponent,Java,Multithreading,Swing,User Interface,Paintcomponent,我需要一个如何使我的程序正常工作的提示。我创建了一个从JComponent扩展而来的类。我还设法使整个面板的白色。现在,我正试图使我的线程狼将画在JCOmponent上,并将移动一次。不幸的是,我的代码不起作用,我想这是因为狼没有被画在白板上。如何更改程序以使其工作。我将非常感谢你的帮助 public class Plansza extends JComponent implements ActionListener { static int width = 500; st

我需要一个如何使我的程序正常工作的提示。我创建了一个从JComponent扩展而来的类。我还设法使整个面板的白色。现在,我正试图使我的线程狼将画在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) {        
        }


}   

在许多现代语言中,UI在主线程上运行,您不能从另一个线程修改它(或者至少不应该修改)。()

尽管repaint()和revalidate()是线程安全的,并且它们有自己的invokeAndWait,但您必须使用类似的方式创建UI

SwingUtilities.invokeAndWait(new Runnable() {
    public void run() {
        createGUI();
     }
});
因此,每次绘制主面板时都会创建“绘制狼”线程

Oracle还建议调用
super.paintComponent(g)输入


我建议您完全阅读《Oracle Swing指南》,然后尝试修改Flipper coin示例,使其能够按照您的意愿工作()

首先,请看一看并了解有关如何在Swing中执行绘制的详细信息

查看有关处理Swing a线程的详细信息

基本上,仅对显示的容器上的组件进行绘制。这意味着只有您的
Plansza
才会被绘制,但只有当它被添加到类似
JFrame
的内容中时才会被绘制,
JFrame
才可见

这意味着,
Wilk
永远无法绘制,因此它的
paintComponent
方法变得有些毫无意义(在此上下文中)

您可以使用某种方式将要绘制的内容从
Wilk
(控制器)传达到
Plansza
(视图)。这通常通过使用某种模型来实现,该模型允许控制器更改其状态,并允许视图渲染该状态

例如

这是实现的基本演示

模型驱动视图,控制器驱动模型。这样,只要满足模型的契约,各个元素就相互独立

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();
        }

    }

}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Rectangle;
导入java.util.ArrayList;
导入java.util.Iterator;
导入java.util.List;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
公共类模型{
公共静态void main(字符串[]args){
新模型();
}
公共模型(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
MutableModel模型=新的DefaultModel();
控制器=新控制器(型号);
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新视图(模型));
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
controller.start();
}
});
}
公共接口模型{
公共矩形getBounds();
公共维度getSize();
公共void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
}
公共接口可变模型扩展模型{
公共无效更新();
}
公共类DefaultModel实现了MutableModel{
专用最终尺寸=新尺寸(200200);
私有最终矩形边界=新矩形(95,95,10,10);
私有int-xDelta=((int)(Math.random()*5))+1;
private int yDelta=((int)(Math.random()*5))+1;
私有列表更改侦听器;
公共模型(){
changeListeners=新的ArrayList(25);
}
@凌驾
公共无效addChangeListener(ChangeListener listener){
添加(监听器);
}
@凌驾
public void removeChangeListener(ChangeListener listener){
移除(侦听器);
}
受保护的无效fireStateChanged(){
if(changeListeners.size()>0){
ChangeEvent evt=新的ChangeEvent(本);
Iterator it=changeListeners.Iterator();
while(it.hasNext()){
ChangeListener=it.next();
stateChanged(evt);
}
}
}
@凌驾
公共维度getSize(){
返回大小;
}
@凌驾
公共矩形getBounds(){
返回边界;
}
@凌驾
公共无效更新(){
边界x+=xDelta;
bounds.y+=yDelta;
if(界限x<0){
边界x=0;
xDelta*=-1;
}else if(bounds.x+bounds.width>size.width){
bounds.x=size.width-bounds.width;
xDelta*=-1;
}
if(界限y<0){
边界y=0;
yDelta*=-1;
}else if(bounds.y+bounds.height>size.height){
bounds.y=size.height-bounds.height;
yDelta*=-1;
}
fireStateChanged();