CS 112 - Introduction to Computer Science II
Homework #8

Due: At the beginning of class 24.

NOTE: This work is to be done in pairs.  I strongly recommend the practice of Pair Programming described simply here.  Although team members are permitted to divide work, each team member should be able to informally present all work of his/her teammate.

JavaFX Pane for Birds of a Feather Card

In this exercise, you will create a dynamically resizable and mutable Pane for rendering a playing card well-suited to the solitaire card game Birds of a Feather.  This will offer practice in the use of images, shapes, layouts, as well as the use of JavaFX properties that we can use to "listen" for changes to trigger dynamic updates.

In the game Birds of a Feather, it is especially important to be able to visually judge both rank and suit similarity of cards, so we will create minimalist cards that make use of Charles Wards' COLOURCRACK color palette with color-blind-friendly colors, and represent each rank by generating a grid of 4-colored suit symbols proportional to the rank of the card (A=1, 2=2, ..., T=10, J=11, Q=12, K=13).

You will download CardPaneTest.java to test your development of CardPane.java.  CardPane extends Pane of JavaFX.  Your CardPane will maintain a strict aspect ratio of the standard Poker playing card:

	/**
	 * Standard Poker card width/height is 635/889.
	 */
	public static final double ASPECT_RATIO = 635.0/889.0; 

 

Your images, "suit-green-club-100.png", "suit-pink-heart-100.png", "suit-black-spade-100.png", "suit-blue-diamond-100.png", should be loaded directly from directory /Courses/cs112/images/suits/ so that we have no more than one set of these images on our system.  (You may copy these to your personal machines, but make sure your submitted code works only with these original image files and not copies of them.)  You will need to learn how to load images from files in different directories.

Your CardPane has only one public method, its constructor:

	public CardPane(StringProperty cardStr) {
		super();
		...
	}

You may, of course, have as many private fields and methods as you find useful.  For example, it will be helpful to create a method such as "changeCard()" so that you can attach that method call as a behavior of a listener you attach to properties.  When a property changes, you can listen for the changes like so:

		cardStr.addListener(new ChangeListener<String>(){
	        	public void changed(ObservableValue<? extends String> o, String oldVal, String newVal){
	        		changeCard();
	        	}
		});

This can be abbreviated with a lambda expression to:

		cardStr.addListener((observableValue, oldValue, newValue) -> changeCard());

Any code placed in the changeCard method will be triggered by a property change event.  You will want to add listeners to height and width properties in order to dynamically resize your rendered card to maintain the above aspect ratio.

The CardPaneTest code will allow you to inspect different card renderings of your CardPane by typing two-character card names (e.g. "3C", "qH", "AS", "td") into the upper-right text field. The StringProperty of this text field will be sent to the constructor of your CardPane, allowing you to add a listener as shown above.  Here is an example of how my CardPane is displayed at the start of CardPaneTest:

If I have a text field entry that has more or fewer than 2 characters, nothing is displayed in the pane.  If I have an invalid two-character entry, nothing is displayed.  A valid two-character entry is one that has a first rank character of the set {'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K'} and a second suit character of the set {'C', 'H', 'S', 'D'}.  Also, lowercase letters of those listed are allowed as if the user had typed them as uppercase.  (The text property is not modified.  This is only an internal uppercase conversion.)  As I edit the field, no card is shown until a valid two-character entry is given:

In these examples, we see that the rank number of suits of the card is displayed left-to-right, top-to-bottom in a centered, 5 row, 3 column grid.  (Note the lowercase entry.)  Further, note that the card has a white background with rounded corners, a margin between the side of the card and the grid, and adequate padding between the suit images (i.e. the suit images do not touch each other or the edges).

Further, as I drag the corner of the PrimaryStage window to resize it, the card within the pane remains centered and extends to the edges of the pane while maintaining the same aspect ratio:

Notes:

There are many ways to accomplish this task.  You'll need to do some text reading and online searching to find examples of how to do different parts of this assignment (e.g. image scaling, listening for width/height changes, etc.).  That is the way of GUI design.  The submission system will collect your CardPane.java only and will not offer feedback.  These will be graded manually according to the following grading rubric:

Rubric: (20 points total)