java - JPanel 中的多个动画(线程)

标签 java multithreading swing animation jpanel

我正在尝试用 Java 编写棋盘游戏。

我有 11 个类,包括 Main。 Board 类,扩展 JPanel 并绘制棋盘图像和骰子图像。 Player 类扩展了 JCoponent 并实现了 Runnable(Thread)。每个玩家实例都是一个在棋盘上移动的典当动画。玩家类在棋盘上绘制棋子。

模式
代码如下:

Board b=new Board(); 
Player p=new Player();
b.add(p);
JPanel panel=new JPanel();
panel.add(b);
add(panel); //adding the panel to the frame.

问题是我不能同时在棋盘上拥有多个棋子。我已经尝试在另一个类中重新绘制所有玩家(作为非动画),但它不起作用。我也尝试过 JLayeredPane 但也许我做错了什么。不幸的是,我无法改变上述模式,所以不要提出这个建议。

预先感谢您的帮助。

P.S:我无法发布任何代码,因为它太大了。
P.P.S:如果你问我,我会提供更多说明。

编辑:我修改我的问题。是否可以在同一个面板上同时显示两个动画?如果答案是肯定的..我该怎么做?

最佳答案

很可能有许多组件同时移动。可以使用 javax.swing.Timer 或 SwingWorker 来实现此功能。

这是一个向您展示这一点的简单示例。它将 16 个棋子放在棋盘上,并将它们随机地从一个地方移动到另一个地方。

Board animation

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestAnimation {

    private static final String PAWN_URL = "http://files.chesskidfiles.com/images_users/tiny_mce/BoundingOwl/bishop_happywhite.png";

    private Image pawn;

    private Map<Location, Pawn> pawnLocations = new HashMap<>();

    private Board board;

    private Timer timer;

    private JLayeredPane glassPane;

    public TestAnimation() {
        try {
            pawn = new ImageIcon(new URL(PAWN_URL)).getImage();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    private static class Location {
        public final int row;
        public final int col;

        public Location(int row, int col) {
            super();
            this.row = row;
            this.col = col;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + col;
            result = prime * result + row;
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            Location other = (Location) obj;
            return (col == other.col && row == other.row);
        }
    }

    private static class Cell extends JPanel {

        private final Location location;

        public Cell(Location location) {
            super(new BorderLayout());
            this.location = location;
            setOpaque(true);
            setBackground(((location.row + location.col) % 2) == 0 ? Color.WHITE : Color.BLACK);
        }

        @Override
        protected void addImpl(Component comp, Object constraints, int index) {
            while (getComponentCount() > 0) {
                remove(0);
            }
            super.addImpl(comp, constraints, index);
        }
    }

    private static class Board extends JPanel {

        private Map<Location, Cell> cells = new HashMap<>();

        public Board() {
            super(new GridLayout(8, 8));
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    Cell cell = new Cell(new Location(i, j));
                    add(cell);
                    cells.put(new Location(i, j), cell);
                }
            }
        }

        public void add(Pawn pawn, Location location) {
            cells.get(location).add(pawn);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        public Cell getCell(Location location) {
            return cells.get(location);
        }
    }

    private class Pawn extends JComponent {
        public Pawn() {
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(pawn, 0, 0, getWidth(), getHeight(), this);
        }
    }

    protected void initUI() {
        JFrame frame = new JFrame(TestAnimation.class.getSimpleName());
        board = new Board();
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 2; j++) {
                Location location = new Location(i, j);
                Pawn aPawn = new Pawn();
                board.add(aPawn, location);
                pawnLocations.put(location, aPawn);
            }
        }
        for (int i = 0; i < 8; i++) {
            for (int j = 6; j < 8; j++) {
                Location location = new Location(i, j);
                Pawn aPawn = new Pawn();
                board.add(aPawn, location);
                pawnLocations.put(location, aPawn);
            }
        }
        timer = new Timer(7000, new Animation());
        timer.setInitialDelay(0);
        timer.setRepeats(true);
        timer.setCoalesce(false);
        glassPane = new JLayeredPane();
        glassPane.setOpaque(false);
        frame.add(board);
        frame.setGlassPane(glassPane);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        timer.start();
        glassPane.setVisible(true);
    }

    public class Animation implements ActionListener {

        private Map<Location, Pawn> futureLocations;

        private Random random = new Random();

        private Timer subTimer;

        private List<Pawn> movingPawns;

        private Map<Pawn, Point> originalCoordinates = new HashMap<>();
        private Map<Pawn, Point> futureCoordinates = new HashMap<>();

        @Override
        public void actionPerformed(ActionEvent e) {
            futureLocations = new HashMap<>();
            movingPawns = new ArrayList<>();
            for (Pawn p : pawnLocations.values()) {
                int row = random.nextInt(8);
                int col = random.nextInt(8);
                Location location;
                while (futureLocations.containsKey((location = new Location(row, col)))) {
                    row = random.nextInt(8);
                    col = random.nextInt(8);
                }
                futureLocations.put(location, p);
                Cell futureCell = board.getCell(location);
                futureCoordinates.put(p, SwingUtilities.convertPoint(futureCell, 0, 0, glassPane));
                movingPawns.add(p);
            }
            for (Pawn p : movingPawns) {
                Point locationInGlassPane = SwingUtilities.convertPoint(p.getParent(), 0, 0, glassPane);
                glassPane.add(p);
                p.setLocation(locationInGlassPane);
                originalCoordinates.put(p, locationInGlassPane);
            }
            subTimer = new Timer(50, new AnimationSteps());
            subTimer.setInitialDelay(0);
            subTimer.setCoalesce(true);
            subTimer.setRepeats(true);
            subTimer.start();
        }

        public class AnimationSteps implements ActionListener {

            private int step = 0;

            @Override
            public void actionPerformed(ActionEvent e1) {
                if (step < 50 + 1) {
                    for (Pawn p : movingPawns) {
                        Point p1 = originalCoordinates.get(p);
                        Point p2 = futureCoordinates.get(p);
                        int x = (int) (p1.x + ((p2.x - p1.x) * (double) step / 50));
                        int y = (int) (p1.y + ((p2.y - p1.y) * (double) step / 50));
                        p.setLocation(x, y);
                    }
                } else {
                    for (Entry<Location, Pawn> e : futureLocations.entrySet()) {
                        board.add(e.getValue(), e.getKey());
                    }
                    board.revalidate();
                    subTimer.stop();
                    pawnLocations = futureLocations;
                }
                step++;

            }

        }
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestAnimation().initUI();
            }
        });
    }
}

关于java - JPanel 中的多个动画(线程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28282858/

相关文章:

java - 覆盖方法所需的返回类型

c# - ASP.NET 线程 - 我可以使用异步方法还是使用线程?

c# - 事件队列无法正常工作 winforms

java - 按钮 b2 =stop 未监听

java - Gradle多项目-在项目之间共享源代码

java - JProgressBar 未正确显示

multithreading - 可以从另一个 QThread 安全地发出 Qt 信号吗

java.lang.numberformatException 空字符串 java awt

java - 绘制后组件不显示

java - Android onClick 自定义PageAdapter