绘制分层形状

时间:2015-04-09 01:13:52

标签: java swing user-interface paint

我正在尝试为连接四游戏创建GUI,我希望芯片在它们掉落时动画。我希望芯片看起来像是通过板子的部分后面没有被切掉。我遇到的问题是,如果我打印出电路板(带有孔的部分),首先将掉落的芯片放在它上面,如果我先打印出芯片,电路板将覆盖它(因为它是只是一个矩形)。有没有办法在不为背景图像创建复杂多边形的情况下这样做?

这是我到目前为止的代码:

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

    }

}

}

2 个答案:

答案 0 :(得分:3)

好的,我至少有两种方法可以考虑这样做,一种方法是创建一个BufferedImage并使用AlphaComposite来解决问题&#34;在它的洞,另一个是使用Area并从中减去洞......

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

使用Area

这个例子演示了Area的使用,它有漏洞&#34; pocked&#34;出来......

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

    }

}

答案 1 :(得分:0)

以下是我几年前在网上找到的一些代码:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class CompositeBoardTest extends JFrame {
    private static int size = 400;
    private static int offset = 10;
    private static int ovalSize = size/4 - offset*2;
    private static int pos = offset/2;
    private static int incr = size/4;

    public static void main( String[] args ) throws Exception {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() { new CompositeBoardTest(); }
        } );
    }

    public CompositeBoardTest() {
        super( "CompositeBoardTest" );
        setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

        Board board = new Board();
        getContentPane().add( board );
        setSize( size, size+34 );
        setVisible( true );
    }

    static class Board extends JPanel implements ActionListener {
        private int[][] pieces = new int[4][4];
        private Piece addingPiece = null;
        private Timer pieceDropped = null;

        public Board() {
            setPreferredSize( new Dimension( size, size ) );
            setBounds( 0, 0, size, size );
//          pieceDropped = new Timer( 10, this );
            pieceDropped = new Timer( 20, this );
            addMouseListener( new MouseAdapter() {
                public void mousePressed( MouseEvent e ) {
                    int column = ( e.getPoint().x-pos )/incr;
                    addPiece( column );
                }
            });
        }

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

            Graphics2D g2d = (Graphics2D) g;
            Composite comp = g2d.getComposite();

            Dimension d = getSize();
            int w = d.width;
            int h = d.height;

            BufferedImage buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D gbi = buffImg.createGraphics();

            // Clear area
            g2d.setColor( Color.WHITE );
            g2d.fillRect( 0, 0, w, h );

            // Draw screen
//          gbi.setColor( Color.YELLOW );
            gbi.setColor( Color.BLUE );
            gbi.fillRect( 0, 0, w, h );

            // Draw pieces or holes
            gbi.setColor( Color.RED );
            for ( int row = 0 ; row < 4 ; row++ ) {
                for ( int column = 0 ; column < 4 ; column++ ) {
                    if ( pieces[row][column] == 1 ) {
//                      gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 1.0f ) );
                        gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f ) );
                    } else {
                        gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.CLEAR, 1.0f ) );
                    }
                    gbi.fillOval( incr*column+pos, incr*row+pos, ovalSize, ovalSize );
                }
            }

            // Draw adding piece if we have it
            if ( addingPiece != null ) {
                gbi.setComposite( AlphaComposite.getInstance( AlphaComposite.DST_OVER, 1.0f ) );
                gbi.fillOval( addingPiece.x, addingPiece.y, ovalSize, ovalSize );
            }

            // Draws the buffered image.
            g2d.drawImage(buffImg, null, 0, 0);

            g2d.setComposite( comp );
        }

        public void addPiece( int column ) {
            if ( addingPiece == null ) {
                if ( pieces[0][column] == 0 ) {
                    addingPiece = new Piece();
                    addingPiece.row = 0;
                    addingPiece.column = column;
                    addingPiece.x = incr*column+pos;
                    addingPiece.y = 0;
                    pieceDropped.start();
                } else {
                    getToolkit().beep();
                }
            }
        }

        public void actionPerformed( ActionEvent e ) {
            if ( addingPiece != null ) {
                addingPiece.y += 5;
                int row = ( addingPiece.y - pos )/incr + 1;
                if ( row > 3 || pieces[row][addingPiece.column] == 1 ) {
                    pieces[row-1][addingPiece.column] = 1;
                    addingPiece = null;
                    pieceDropped.stop();
                }
            }
            repaint();
        }
    }

    private static class Piece {
        public int row, column, x, y;
    }
}

单击列以开始动画。