Java: Example - Card Demo
This program displays card images, which can then 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.
|
CardDemo1.java
- The main program as a subclass of JFrame
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 |
// File : GUI-lowlevel/cards1/cards/CardDemo1 // Purpose: Basic GUI to show dragging cards. // Illustrates how to load images from files. // Author : Fred Swartz - 2007-02-19 - Placed in public domain. // // Enhancements: // * This really doesn't have a user interface beyond dragging. // It doesn't do anything, and therefore has no model. // Make it play a game. // * Needs to have a Deck class to shuffle, deal, ... Cards. // Persumably based on ArrayList<Card>. // * Perhaps a Suit and Face class would be useful. // * Like Deck, there would also be a class for Hand. // * May need Player class too. package cards; import java.net.URL; import javax.swing.*; ////////////////////////////////////////////////////////////// class CardDemoGUI class CardDemo1 extends JFrame { //=================================================================== fields private static Card[] _deck = new Card[52]; //===================================================================== main public static void main(String[] args) { CardDemo1 window = new CardDemo1(); window.setTitle("Card Demo 1"); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setContentPane(new CardTable(_deck)); window.pack(); window.setLocationRelativeTo(null); window.setVisible(true); } //============================================================== constructor public CardDemo1() { //... ClassLoader is where to get images from this .jar file. ClassLoader cldr = this.getClass().getClassLoader(); int n = 0; // Which card. int xPos = 0; // Where it should be placed initially. int yPos = 0; //... Read in the cards using particular file name conventions. // Images for the backs and Jokers are ignored here. String suits = "shdc"; String faces = "a23456789tjqk"; for (int suit=0; suit < suits.length(); suit++) { for (int face=0; face < faces.length(); face++) { //... Get the image from the images subdirectory. String imagePath = "cards/images/" + faces.charAt(face) + suits.charAt(suit) + ".gif"; URL imageURL = cldr.getResource(imagePath); ImageIcon img = new ImageIcon(imageURL); //... Create a card and add it to the deck. Card card = new Card(img); card.moveTo(xPos, yPos); _deck[n] = card; //... Update local vars for next card. xPos += 5; yPos += 4; n++; } } } } |
CardTable.java
- A subclass of JComponent for displaying the cards
This displays the cards, and listens to mouse events so that it can drag the cards around. There should really be a "model" of a card game, and this would simply interrogate the model to find out what to display, and pass mouse actions to the model.
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 121 122 123 124 125 126 127 128 129 |
// File : GUI-lowlevel/cards1/cards/CardTable.java // Purpose: This is just a JComponent for drawing the cards that are // showing on the table. // // Author : Fred Swartz - February 19, 2007 - Placed in public domain. // // Enhancements: // * Use model. Currently, it is initialized with a whole deck of cards, // but instead it should be intialized with a "model" which // it should interrogate (calling model methods) to find out what // should be displayed. // * Similarly, actions by the mouse might be used to set things in the // model, Perhaps by where it's dragged to, or double-clicked, or // with pop-up menu, or ... package cards; import java.awt.*; import java.awt.event.*; import javax.swing.*; ////////////////////////////////////////////////////////////////////// CardTable public class CardTable extends JComponent implements MouseListener, MouseMotionListener { //================================================================ constants private static final Color BACKGROUND_COLOR = Color.GREEN; private static final int TABLE_SIZE = 400; // Pixels. //=================================================================== fields //... 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; // Should really be in a model, but ... private Card _currentCard = null; // Current selected card. //============================================================== constructor public CardTable(Card[] deck) { _deck = deck; // Should be passed a model. //... Initialize graphics setPreferredSize(new Dimension(TABLE_SIZE, TABLE_SIZE)); setBackground(Color.blue); //... Add mouse listeners. addMouseListener(this); addMouseMotionListener(this); } //=========================================================== paintComponent @Override public void paintComponent(Graphics g) { //... Paint background int width = getWidth(); int height = getHeight(); g.setColor(BACKGROUND_COLOR); g.fillRect(0, 0, width, height); //... Display the cards, starting with the first array element. // The array order defines the z-axis depth. for (Card c : _deck) { c.draw(g, this); } } //====================================================== method mousePressed // Check to see if press is within any card. // If it is, // * Set _currentCard so mouseDragged knows what to drag. // * Record where in the image (relative to the upper left coordinates) // the mouse was clicked, because it looks best if we drag from there. // 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 (testCard.contains(x, y)) { //... Found, remember this card for dragging. _dragFromX = x - testCard.getX(); // how far from left _dragFromY = x - testCard.getY(); // how far from top _currentCard = testCard; // Remember what we're dragging. break; // Stop when we find the first match. } } } //============================================================= mouseDragged // Set x,y to mouse position and repaint. public void mouseDragged(MouseEvent e) { if (_currentCard != null) { // Non-null if pressed inside card image. int newX = e.getX() - _dragFromX; int newY = e.getY() - _dragFromY; //--- Don't move the image off the screen sides newX = Math.max(newX, 0); newX = Math.min(newX, getWidth() - _currentCard.getWidth()); //--- Don't move the image off top or bottom newY = Math.max(newY, 0); newY = Math.min(newY, getHeight() - _currentCard.getHeight()); _currentCard.moveTo(newX, newY); this.repaint(); // Repaint because position changed. } } //======================================================= method mouseExited // Turn off dragging if mouse exits panel. public void mouseExited(MouseEvent e) { _currentCard = null; } //=============================================== 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 } |
Card.java
- Class representing one card
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 |
// File : GUI-lowlevel/cards1/cards/Card.java // Purpose: Represents one card. // Author : Fred Swartz - February 19, 2007 - Placed in public domain. // // Enhancements: // * Needs to have Suit and Face value. package cards; import java.awt.*; import javax.swing.*; /////////////////////////////////////////////////////////////////////////// Card class Card { //=================================================================== fields private ImageIcon _image; private int _x; private int _y; //============================================================== constructor public Card(ImageIcon image) { _image = image; } //=================================================================== moveTo public void moveTo(int x, int y) { _x = x; _y = y; } //================================================================= contains public boolean contains(int x, int y) { return (x > _x && x < (_x + getWidth()) && y > _y && y < (_y + getHeight())); } //================================================================= getWidth public int getWidth() { return _image.getIconWidth(); } //================================================================ getHeight public int getHeight() { return _image.getIconHeight(); } //===================================================================== getX public int getX() { return _x; } //===================================================================== getY public int getY() { return _x; } //===================================================================== draw public void draw(Graphics g, Component c) { _image.paintIcon(c, g, _x, _y); } } |