Text-Based Card Game with Deck, Hand, and Card Classes
The main panel of the card game uses a BorderLayout, with the drawing surface in CENTER and the subpanel of three buttons in SOUTH.
Laying Out the Card Game Window
Imagine a card game where you look at one playing card and must guess whether the next card will be higher or lower in value. Aces count as the lowest card in this game. Three correct guesses win the round, and a single wrong guess ends it. The text-based version of this game only needed the console. A graphical version needs a window that shows the cards, displays a message to the player, and offers buttons for making predictions and starting a new game.
Building that window is a design problem before it is a coding problem. You have to decide what goes where, which object owns the drawing, and which object reacts when the player presses a button. This article works through those decisions in order, starting with the layout of the main window.
What do you think happens?
The main panel has a large area that shows the cards and a message, and a row of three buttons. Which region of the layout should the large area occupy?
Reveal answer
CENTER
The drawing surface, which shows the cards and message, occupies the CENTER region. The subpanel holding the three buttons occupies SOUTH. Keep this pairing in mind, because the rest of the design builds on it.
Five Regions of a BorderLayout
The main panel of the card game is the container that holds everything else, and it uses a layout called BorderLayout to place its parts. A BorderLayout has five regions, named NORTH, SOUTH, EAST, WEST, and CENTER. You place a component into one of these regions, and the layout positions it accordingly.
BorderLayout: a layout that divides a container into five named regions, NORTH, SOUTH, EAST, WEST, and CENTER. Each region can hold one component, and any region you leave unused simply contributes no visible content.
Tracing the Window Layout
Placing the Card Game Components
The main panel must hold a drawing surface that shows the cards and message, and a subpanel with three buttons. Decide which BorderLayout region each component goes into, and state what happens to the regions you do not use.
- 1Identify the large area
The drawing surface shows the cards and the message. It is the largest visible part of the window, so it belongs in CENTER.
- 2Identify the button row
The three buttons are grouped into a subpanel. A row of buttons along the bottom of the window fits the SOUTH region.
- 3Assign the components
Put the drawing surface into CENTER and the button subpanel into SOUTH.
- 4Account for the remaining regions
NORTH, EAST, and WEST receive no components. They contribute no visible content, which is why the design does not need anything in them.
CENTER holds the CardPanel drawing surface, SOUTH holds the button subpanel, and NORTH, EAST, and WEST stay empty.
Why the Drawing Surface Is Its Own Class
The card game is built from two JPanel classes that play different roles. The outer panel is the class HighLowGUI, which is itself a subclass of JPanel. Its constructor creates the other components, sets up event handling, and lays out the components in the BorderLayout. The inner panel is a nested class named CardPanel, also a subclass of JPanel, and it is the drawing surface.
Custom JPanel subclass: a class that extends JPanel so that the panel carries extra behavior the standard JPanel does not provide. In this game, CardPanel is that subclass.
Why make the drawing surface a subclass instead of using ready-made components? The source explains that the cards and the message are not built from standard components. Instead, they are drawn with the graphics context inside the panel's paintComponent() method. A custom subclass is the natural home for that code, because the drawing logic belongs to the same object that is responsible for the display. Keeping the painting code inside CardPanel means the object that shows the cards also knows how to draw them.
Notice the split of responsibilities in the diagram. HighLowGUI arranges the window. The button subpanel groups the controls. CardPanel does the drawing, and it is also the object that listens for events from the buttons. The buttons do not paint anything themselves, and they do not decide what the game does next.
Tracing a Button Click
Event handling is the link between a user action and the code that responds to it. In this design the player clicks a button, and the event has to reach the object that knows what to do. The source states that the drawing surface listens for events from the three buttons. The buttons are therefore not the ones deciding the outcome. They only report that they were pressed.
- 1The player clicks one of the three buttons in the SOUTH subpanel.
- 2The button reports that it was pressed. It does not choose the result of the guess.
- 3The event reaches
CardPanel, which is the object listening for events from the buttons. - 4
CardPanelhandles the event, and the next state of the game is decided from there. - 5The cards and message are shown again through the drawing code in
paintComponent().
Mistakes When Designing the Card Window
Common mistake Believing the button decides the outcome of the guess
What it looks likeA learner assumes that clicking the higher button itself checks whether the next card is higher.
Why it failsThe source says the buttons only report that they were pressed. The drawing surface listens for those events and handles them.
Do this insteadTrace the click to the listening object, which is CardPanel, before deciding where the reaction happens.
Common mistake Putting the drawing code in the button subpanel
What it looks likeA learner paints the cards inside the class that builds the buttons.
Why it failsThe drawing logic belongs to the object responsible for the display. In this design, that object is the
CardPaneldrawing surface.Do this insteadPlace the cards and message drawing inside the CardPanel subclass, in its paintComponent() method.
Common mistake Filling every BorderLayout region
What it looks likeA learner feels the window looks incomplete and adds a component to NORTH, EAST, and WEST.
Why it failsThe design uses only CENTER and SOUTH. An unused region contributes no visible content and the design does not need a component there.
Do this insteadLeave unused regions empty unless the design calls for a component in them.
Common mistake Confusing the outer HighLowGUI panel with the inner CardPanel drawing surface
Practice: Trace a Click and Place a Component
A teammate proposes adding a new status label that should appear along the top of the window above the drawing surface. Using only the design described in this article, decide which BorderLayout region the label should go into, then trace what happens when the player clicks one of the three buttons. Name each object the event passes through, and say which one reacts to it.
Hints
- Think about which regions are already used and which are still empty.
- The top of a window corresponds to one of the five named regions.
- Remember that the buttons only report presses, and the listening object responds.
Key Takeaways
- A
BorderLayoutdivides a container into five regions named NORTH, SOUTH, EAST, WEST, and CENTER, and unused regions can stay empty. - The card game's main panel puts the
CardPaneldrawing surface in CENTER and the three-button subpanel in SOUTH. CardPanelis a nestedJPanelsubclass because it carries the custom painting code inpaintComponent()and the event listening for the buttons.- Button presses are reported by the buttons and handled by the listening drawing surface, so tracing a click means following the event to that object.