Search code examples
javaswinggraphicsjpanelcube

How to create a cube in swing?


I am trying to make a class that when invoked by a JPanel, creates a cube. What I have seen though, is something called a ColorCube, which requires a "Universe" of some sort, and a Canvas, though I didn't find this method to be compatible with JPanel.

TO clarify, I am not asking how to create a custom JComponent(exactly), nor am I asking how to add color or rotate it, just how to create a class that when invoked by a JPanel renders a cube to the screen.


Solution

  • All you really need are x, y, and size passed to the Cube class, then

    • Take those arguments and build an array of corners points for a first square and also corner points for a second shifted square. See methods getCubeOnePoints and getCubeTwoPoints methods in the Cube class.

    • Draw the first square. Draw the second square, and connect the points from the point arrays. See the drawCube method in the Cube class.

    • Create an instance of the Cube class passing necessary arguments, and draw the cube. See CubePanel constructor and paintComponent method

    enter image description here

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class CubePanel extends JPanel{
        private static final int D_W = 400;
        private static final int D_H = 400;
    
        Cube cube;
        public CubePanel() {
            cube = new Cube(75, 75, 200, 50);
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            cube.drawCube(g);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(D_W, D_H);
        }
    
        public class Cube {
            int x, y, size, shift;
            Point[] cubeOnePoints;
            Point[] cubeTwoPoints;
            public Cube(int x, int y, int size, int shift) {
                this.x = x;
                this.y = y;
                this.size = size;
                this.shift = shift;
                cubeOnePoints = getCubeOnePoints();
                cubeTwoPoints = getCubeTwoPoints();
            }
    
            private Point[] getCubeOnePoints() {
                Point[] points = new Point[4];
                points[0] = new Point(x, y);
                points[1] = new Point(x + size, y);
                points[2] = new Point(x + size, y + size);
                points[3] = new Point(x, y + size);
                return points;
            }
    
            private Point[] getCubeTwoPoints() {
                int newX = x + shift;
                int newY = y + shift;
                Point[] points = new Point[4];
                points[0] = new Point(newX, newY);
                points[1] = new Point(newX + size, newY);
                points[2] = new Point(newX + size, newY + size);
                points[3] = new Point(newX, newY + size);
                return points;
            }
    
            public void drawCube(Graphics g) {
                g.drawRect(x, y, size, size);
                g.drawRect(x + shift, y + shift, size, size);
                // draw connecting lines
                for (int i = 0; i < 4; i++) {
                    g.drawLine(cubeOnePoints[i].x, cubeOnePoints[i].y, 
                            cubeTwoPoints[i].x, cubeTwoPoints[i].y);
                }
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new CubePanel());
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }
    

    UPDATE

    "what if i wanted this in a 3d where the cube could be walked around "

    Just create methods to shift all the xs or ys and call it, then repaint. The method could look something like

        public void shiftLeft() {
            x -= SHIFT_INC;
            for (Point p : cubeOnePoints) {
                p.x -= SHIFT_INC;
            }
            for (Point p : cubeTwoPoints) {
                p.x -= SHIFT_INC;
            }
        }
    

    In the example below, I just call it in a key bind with the key.

        im.put(KeyStroke.getKeyStroke("LEFT"), "shiftLeft");
        getActionMap().put("shiftLeft", new AbstractAction(){
            public void actionPerformed(ActionEvent e) {
                cube.shiftLeft();
                repaint();
            }
        });
    

    enter image description here

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.ActionEvent;
    import javax.swing.AbstractAction;
    import javax.swing.InputMap;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.KeyStroke;
    import javax.swing.SwingUtilities;
    
    public class CubePanel extends JPanel{
        private static final int D_W = 400;
        private static final int D_H = 300;
    
        Cube cube;
        public CubePanel() {
            cube = new Cube(75, 75, 50, 15);
            InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke("RIGHT"), "shiftRight");
            getActionMap().put("shiftRight", new AbstractAction(){
                public void actionPerformed(ActionEvent e) {
                    cube.shiftRight();
                    repaint();
                }
            });
            im.put(KeyStroke.getKeyStroke("LEFT"), "shiftLeft");
            getActionMap().put("shiftLeft", new AbstractAction(){
                public void actionPerformed(ActionEvent e) {
                    cube.shiftLeft();
                    repaint();
                }
            });
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            cube.drawCube(g);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(D_W, D_H);
        }
    
        public class Cube {
            private static final int SHIFT_INC = 5;
            int x, y, size, shift;
            Point[] cubeOnePoints;
            Point[] cubeTwoPoints;
            public Cube(int x, int y, int size, int shift) {
                this.x = x;
                this.y = y;
                this.size = size;
                this.shift = shift;
                cubeOnePoints = getCubeOnePoints();
                cubeTwoPoints = getCubeTwoPoints();
            }
    
            private Point[] getCubeOnePoints() {
                Point[] points = new Point[4];
                points[0] = new Point(x, y);
                points[1] = new Point(x + size, y);
                points[2] = new Point(x + size, y + size);
                points[3] = new Point(x, y + size);
                return points;
            }
    
            private Point[] getCubeTwoPoints() {
                int newX = x + shift;
                int newY = y + shift;
                Point[] points = new Point[4];
                points[0] = new Point(newX, newY);
                points[1] = new Point(newX + size, newY);
                points[2] = new Point(newX + size, newY + size);
                points[3] = new Point(newX, newY + size);
                return points;
            }
    
            public void shiftLeft() {
                x -= SHIFT_INC;
                for (Point p : cubeOnePoints) {
                    p.x -= SHIFT_INC;
                }
                for (Point p : cubeTwoPoints) {
                    p.x -= SHIFT_INC;
                }
            }
    
            public void shiftRight() {
                x += SHIFT_INC;
                for (Point p : cubeOnePoints) {
                    p.x += SHIFT_INC;
                }
                for (Point p : cubeTwoPoints) {
                    p.x += SHIFT_INC;
                }
            }
    
            public void drawCube(Graphics g) {
                g.drawRect(x, y, size, size);
                g.drawRect(x + shift, y + shift, size, size);
                // draw connecting lines
                for (int i = 0; i < 4; i++) {
                    g.drawLine(cubeOnePoints[i].x, cubeOnePoints[i].y, 
                            cubeTwoPoints[i].x, cubeTwoPoints[i].y);
                }
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new CubePanel());
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }