java - 绘制分层形状

标签 java swing user-interface paint

我正在尝试为四人连线游戏创建 GUI,我希望筹码在掉落时呈现动画效果。我希望筹码看起来像是从没有被切掉的棋盘部分后面经过。我遇到的问题是,如果我先打印出电路板(上面有孔的那 block ),掉落的芯片就会在上面,如果我先打印出芯片,电路板就会盖住它(因为它是只是一个矩形)。有什么方法可以在不为背景图像创建一些复杂的多边形的情况下做到这一点?

这是我目前的代码:

public class ConnectFourGrid extends JPanel
{
ConnectFour game;

boolean animate = false;
int animateRow = 0;
int animateCol = 0;
int dropYPos = -30;
Timer dropTimer = new Timer(2, new animateListener());

ConnectFourGrid()
{
    this.setPreferredSize(new Dimension(ConnectFour.NUM_OF_COLUMNS * 100, ConnectFour.NUM_OF_ROWS * 100));
}

class animateListener implements ActionListener
{

    @Override
    public void actionPerformed(ActionEvent arg0) 
    {
        dropYPos += 5;

        if (dropYPos == (animateRow * 100) + 10)
        {
            dropTimer.stop();
            dropYPos = -30;
            animate = false;
        }
        repaint();
    }

}

public void setGame(ConnectFour game) { this.game = game; }
public ConnectFour getGame() { return game; }

public void animate(int row, int col)
{
    animate = true;
    animateRow = row;
    animateCol = col;
    dropTimer.start();
}

public void paintComponent(Graphics g) 
{
    super.paintComponent(g);

    for (int row = 0; row < ConnectFour.NUM_OF_ROWS; row++)
    {
        for (int col = 0; col < ConnectFour.NUM_OF_COLUMNS; col++)
        {
            g.setColor(Color.BLUE);
            g.fillRect(col * 100, row * 100, 100, 100);

            if (game.getCurrentGameState()[row][col] == 0)
                g.setColor(Color.WHITE);
            else if (game.getCurrentGameState()[row][col] == 1)
                g.setColor(Color.RED);
            else 
                g.setColor(Color.YELLOW);

            g.fillOval( col * 100 + 5, row * 100 + 10, 80, 80);

        }
    }

    if (animate)
    {
        if (game.getCurrentPlayer() == 1)
            g.setColor(Color.YELLOW);
        else
            g.setColor(Color.RED);

        g.fillOval(animateCol * 100 + 5, dropYPos, 80, 80);

    }

}

}

最佳答案

好吧,我至少可以想到两种方法,一种是创建一个 BufferedImage 并使用 AlphaComposite 在其中“戳”洞,另一种是使用 Area 并从中减去空洞...

BufferedImage 方法可以更高效,因为您只需要在需要时创建图像,但也可能有点复杂。

使用区域

这个例子演示了 Area 的使用,其中有“凹”出来的洞...

ConnectFour

import java.awt.AlphaComposite;
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.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setBackground(Color.RED);
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int width = getWidth() - 20;
            int height = getHeight() - 20;

            Area area = new Area(new Rectangle(10, 10, width, height));

            int cellWidth = width / 4;
            int cellHeight = height / 4;

            for (int row = 0; row < 4; row++) {
                int yPos = 10 + (row * cellHeight);
                for (int col = 0; col < 4; col++) {
                    int xPos = 10 + (col * cellWidth);
                    area.subtract(new Area(new Ellipse2D.Double(xPos + 2, yPos + 2, cellWidth - 4, cellHeight - 4)));
                }
            }

            g2d.setColor(Color.BLUE);
            g2d.fill(area);
            g2d.dispose();
        }

    }

}

使用 BufferedImageAlphaComposite

ConnectFour

import java.awt.AlphaComposite;
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.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage buffer;

        public TestPane() {
            setBackground(Color.RED);
        }

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

        @Override
        public void invalidate() {
            buffer = null;
            super.invalidate();
        }

        protected BufferedImage getBoard() {

            if (buffer == null) {

                int width = getWidth() - 20;
                int height = getHeight() - 20;
                buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = buffer.createGraphics();
                g2d.setColor(Color.BLUE);
                g2d.fillRect(0, 0, width, height);

                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
                g2d.setColor(new Color(0, 0, 0, 0));
                int cellWidth = width / 4;
                int cellHeight = height / 4;

                for (int row = 0; row < 4; row++) {
                    int yPos = (row * cellHeight);
                    for (int col = 0; col < 4; col++) {
                        int xPos = (col * cellWidth);
                        g2d.fill(new Ellipse2D.Double(xPos + 2, yPos + 2, cellWidth - 4, cellHeight - 4));
                    }
                }
                g2d.dispose();

            }

            return buffer;

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            BufferedImage buffer = getBoard();
            int x = (getWidth() - buffer.getWidth()) / 2;
            int y = (getHeight() - buffer.getHeight()) / 2;
            g2d.drawImage(buffer, x, y, this);
            g2d.dispose();
        }

    }

}

关于java - 绘制分层形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29528056/

相关文章:

java - Java 中 close() 的 Python 等价物是什么?

gwt - 使用 GWT 设计管理界面

java - 如何使用 UML 为图形应用程序建模?

java - Spring 批处理 |读取计数 = 过滤 + 写入?

java - 如何在子类中调用父类(super class)方法?

java - 有没有其他方法可以删除字符串中的所有空格?

java - 使用来自其他文本的多行创建 JLabel

java - 需要使用键盘上的箭头键处理 JTable 的行

java - 在弹出窗口中使用 TextBubbleBorder

c++ - 回调函数中的接口(interface)类导致崩溃