# Java: Example - Card Demo

This program reads in a bunch of images (cards) and allows them to be dragged around the screen. The images are stored in an array that represents the z coordinate (what's on top of what). This order is never changed even if a card is dragged, which give the peculiar effect of dragging under.

It is divided into several source files. The card images are in a zipped file.

- `CardDemo.java` functions as either an application (it defines `main()`) or an applet (it subclasses `JApplet`).
- `CardDemoGUI.java` is a subclass of JPanel that creates the GUI interface. A JPanel can be used by either an application or applet.
- `Card.java` represents a single card. This is really only the skeleton of what a real class representing a card would be.
- `cards20.zip` is a zipped file of the card images (.gif), including a back and joker. These images are GPLed, not the MIT License.

### `CardDemo.java` - the main program / applet

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
    // "appletviewer CardDemo.java" works because of the following line.
    // <applet code="CardDemo.class" height="200" width="200"></applet>
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    ///////////////////////////////////////////////////////////// class CardDemo
    /** CardDemo.java - Dragging card images example dual application/applet.
        <ul>
        <li>TODO: The card that is being dragged should be moved to the
            end of the _deck array so that it displays on top.</li>
        <li>TODO: The applet version doesn't work correctly yet because
            it needs to use getCodeBase() in loading the images.</li>
        </ul>

        @author Fred Swartz
        @version 2004-04-22
    */
    public class CardDemo extends JApplet {
        //========================================================== method main
        /** Create JFrame, add the CardDemoPanel, display. */
        public static void main(String[] args) {
            JFrame window = new JFrame();
            window.setTitle("Card Demo");
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.setContentPane(new CardDemoGUI());
            window.pack();
            window.show();
        }//end main

        //=================================================== applet constructor
        /** Constructor for applet */
        public CardDemo() {
            this.setContentPane(new CardDemoGUI());
        }
    }//endclass CardDemo

### `CardDemoGUI.java` provides the GUI to this demo program

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;

    /////////////////////////////////////////////////////////// class CardDemoGUI
    /** CardDemoGUI.java - Panel that allows dragging playing card images.
        @author Fred Swartz
        @version 2004-04-23
    */
    class CardDemoGUI extends JPanel implements MouseListener,
                                                  MouseMotionListener {

        private static final int IMAGE_WIDTH = 73;
        private static final int IMAGE_HEIGHT = 97;
        //--- instance variables
        /** Initial image coords. */
        private int _initX     = 0;   // x coord - set from drag
        private int _initY     = 0;   // y coord - set from drag

        /** Position in image of mouse press to make dragging look better. */
        private int _dragFromX = 0;  // Displacement inside image of mouse press.
        private int _dragFromY = 0;

        private Card[] _deck = new Card[52];
        private Card _currentCard = null;  // Current draggable card.

        //============================================================= constructor
        /** Constructor sets size, colors, and adds mouse listeners.*/
        public CardDemoGUI() {
            //-- Read in the cards
            String suits = "shdc";
            String faces = "a23456789tjqk";
            int cardPosition = 0;
            for (int suit=0; suit<suits.length(); suit++) {
                for (int face=0; face<faces.length(); face++) {
                    ImageIcon img = new ImageIcon("cards/"+ faces.charAt(face)
                                                 + suits.charAt(suit) + ".gif");
                    _deck[cardPosition++] = new Card(img, _initX++, _initY++);
                }
            }

            //-- Initialize graphics
            setPreferredSize(new Dimension(300, 300));
            setBackground(Color.blue);
            //--- Add mouse listeners.
            this.addMouseListener(this);
            this.addMouseMotionListener(this);
        }//endconstructor

        //=================================================== method paintComponent
        /** Ball is drawn at the last recorded mouse listener coordinates. */
        public void paintComponent(Graphics g) {
            super.paintComponent(g);   // Required
            //-- Display the cards, starting with the first array element.
            //   The array order defines the z-axis depth.
            for (int crd=0; crd<_deck.length; crd++) {
                Card c = _deck[crd];
                c.image.paintIcon(this, g, c.x, c.y);
            }
        }//end paintComponent

        //===================================================== method mousePressed
        /** When the mousePressed listener is called,
        check if it's in the area of a card..  If it is,
        <ol>
        <li>_currentCard is set so mouseDragged knows what to drag.</li>
        <li>Record where in the image (relative to the upper left coordinates)
            the mouse was clicked, because it looks best if we drag from there.</li>
        </ol>
        TODO: Move the card to the last position so that it displays on top.
        */
        public void mousePressed(MouseEvent e) {
            int x = e.getX();   // Save the x coord of the click
            int y = e.getY();   // Save the y coord of the click

            //-- Find card image this is in.  Check from top down.
            _currentCard = null;  // Assume not in any image.
            for (int crd=_deck.length-1; crd>=0; crd--) {
                Card testCard = _deck[crd];
                if (x >= testCard.x && x <= (testCard.x + IMAGE_WIDTH)
                        && y >= testCard.y && y <= (testCard.y + IMAGE_HEIGHT)) {
                    _dragFromX = x - testCard.x;  // how far from left
                    _dragFromY = y - testCard.y;  // how far from top
                    _currentCard = testCard;  // Remember what we're dragging.
                    break;   // Stop when we find the first match.
                }
            }
        }//end mousePressed

        //============================================================ mouseDragged
        /** Set x,y to mouse position and repaint. */
        public void mouseDragged(MouseEvent e) {
            if (_currentCard != null) {   // Non-null if pressed inside card image.
                _currentCard.x = e.getX() - _dragFromX;
                _currentCard.y = e.getY() - _dragFromY;

                //--- Don't move the image off the screen sides
                _currentCard.x = Math.max(_currentCard.x, 0);
                _currentCard.x = Math.min(_currentCard.x, getWidth()-IMAGE_WIDTH);

                //--- Don't move the image off top or bottom
                _currentCard.y = Math.max(_currentCard.y, 0);
                _currentCard.y = Math.min(_currentCard.y, getHeight()-IMAGE_HEIGHT);

                this.repaint(); // Repaint because position changed.
            }
        }//end mouseDragged

        //====================================================== method mouseExited
        /** Turn off dragging if mouse exits panel. */
        public void mouseExited(MouseEvent e) {
            _currentCard = null;
        }//end mouseExited

        //=============================================== Ignore other mouse events.
        public void mouseMoved   (MouseEvent e) {}  // ignore these events
        public void mouseEntered (MouseEvent e) {}  // ignore these events
        public void mouseClicked (MouseEvent e) {}  // ignore these events
        public void mouseReleased(MouseEvent e) {}  // ignore these events
    }//endclass CardDemoGUI

### Card.java - Class representing one card

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
    /////////////////////////////////////////////////////////////////// Card
    /** Card.java - Utility class for grouping the image and its position.
        A real card game would expand this into a better class.
        @author Fred Swartz
        @version 2004-04-23
    */
    class Card {
        javax.swing.ImageIcon image;
        int x;
        int y;

        public Card(javax.swing.ImageIcon image, int x, int y) {
            this.image = image;
            this.x = x;
            this.y = y;
        }
    }