且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java线程和graphics2d

更新时间:2023-01-18 11:12:31

首先介绍一下在AWT和Swing中绘画有关在Swing中如何进行绘画的详细信息.

Start by talking a look at Performing Custom Painting and Painting in AWT and Swing for details about how painting is performed in Swing.

请参阅 Swing中的并发,以了解有关处理的详细信息摆动线程.

Take a look at Concurrency in Swing for details about dealing with Swing a threads.

基本上,将仅绘制显示的容器上的组件.这意味着只有您的Plansza会被绘制,只有在将它添加到(直接或以其他方式)诸如JFrame之类并且使JFrame可见的情况下.

Basically, only a component on a displayed container will be painted. This means that only your Plansza will be painted, but only when it's added to a (directly or otherwise) something like JFrame and the JFrame is made visible.

这意味着Wilk永远不能被绘制,因此它的paintComponent方法变得毫无意义(在这种情况下)

This means that Wilk can never be painted and therefore it's paintComponent method becomes somewhat pointless (in this context)

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

What you could use is some way to communicate what you want to paint from your Wilk (controller) to Plansza (view). This is typically achieved via the use of some kind of model, which allows your controller to change it's state and your view to render that state.

例如...

这是模型-的基本演示. Control-View 实现.

模型驱动视图,而控制器驱动模型.这样,只要满足模型的约定,各个要素就可以相互独立

The model drives the view and the controller drives the model. In this way, so long as the contract of the model is meet, the various elements are independent of each other

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

    }

}