Reputation: 87
I'm banging my head against the wall and have a feeling that I'm going about this completely incorrectly. I'm creating a simple hangman game and cannot, for the life of me, get the result of my paintComponent() method to display with the buttons I've created using a JFrame.
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class hangman extends JPanel implements ActionListener {
public static final int youLose=6;
public int wrongGuess;
public String message;
public String theWord;
public StringBuffer guessWord;
public JButton restartButton;
public JButton playButton;
public JTextArea userInput;
public static void main(String[] args) {
hangman h = new hangman();
h.initialize();
}
public void initialize() {
userInput = new JTextArea();
restartButton = new JButton("Restart");
playButton = new JButton("Play");
JFrame frame = new JFrame("Hangman");
frame.setVisible(true);
frame.setLayout(new GridLayout(1,4));
frame.setBounds(0, 0, 500, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(restartButton);
frame.add(playButton);
frame.add(new JLabel("Enter guess: "));
frame.add(userInput);
restartButton.addActionListener(this);
playButton.addActionListener(this);
startGame();
}
public void paintComponent(Graphics g) {
//(left, top, right, bottom)
g.drawLine(90, 250,200,250);
g.drawLine(125,250,125,150);
g.drawLine(125,150,175,150);
g.drawLine(175,150,175,175);
if (wrongGuess > 0){ //head
g.drawOval(170,175,10,12);
}
if (wrongGuess > 1){ //body
g.drawLine(175,187,175,205);
}
if (wrongGuess > 2){ //left arm
g.drawLine(163,185,173,190);
}
if (wrongGuess > 3){ //right arm
g.drawLine(177,190,187,185);
}
if (wrongGuess > 4){ //left leg
g.drawLine(168,220,173,205);
}
if (wrongGuess > 5){ //right leg
g.drawLine(177,205,182,220);
}
g.drawString( message, 40, 290 );
g.drawString( new String (guessWord), 40, 275);
}
public void actionPerformed(ActionEvent event){
if (event.getSource() == restartButton){
restart();
startGame();
}
if (event.getSource() == playButton){
analyzeGuess();
userInput.setText("");
repaint();
}
setVisible(true);
}
public void restart() {
Graphics g = getGraphics();
Dimension d = getSize();
Color c = getBackground();
g.setColor(c);
g.fillRect(0,0,d.width,d.height);
repaint();
}
public void startGame() {
wrongGuess = 0;
String[] wordArray = {"computer", "science", "java", "application", "programming", "university",
"homework", "assignment", "cactus", "flower", "button", "keyboard", "graphic", "interface",
"collegiate", "graduate", "headphones", "building", "radiator", "flora", "fauna", "suitcase",
"sweater", "television", "library", "elevator", "precidence", "ancient", "basketball", "bracket",
"alphabetical", "christmas", "hannukah"};
Random randomGenerator = new Random();
int randomInt = randomGenerator.nextInt(wordArray.length);
theWord = new String(wordArray[randomInt]);
char positions[] = new char[theWord.length()];
for (int i=0; i<theWord.length(); i++) {
positions[i] = '_';
}
String s = new String(positions);
guessWord = new StringBuffer(s);
userInput.setText("");
message="";
repaint();
}
private void analyzeGuess() {
String userGuess, temp;
char letter;
userGuess = userInput.getText();
letter = userGuess.charAt(0);
if (!Character.isLetter(letter)){
message="Invalid character";
return;
}
if (userGuess.length()>1){
message="Only enter one letter";
return;
}
temp = new String(guessWord);
if (temp.indexOf(userGuess) != -1){
message="Letter has already been guessed";
return;
}
if (theWord.indexOf(userGuess) == -1){
message="";
message = new String(message);
wrongGuess++;
message = "You have "+ (youLose-wrongGuess) + " guesses left.";
if (wrongGuess==youLose){
message="You lose! The word was '"+theWord+"'"+"\nClick restart to try again.";
}
return;
}
for (int i=0; i<theWord.length(); i++){
if (theWord.charAt(i) == letter){
guessWord.setCharAt(i, letter);
}
}
temp = new String(guessWord);
if (temp.indexOf('_') == -1){
message="You win!";
return;
}
message="";
repaint();
}
}
Upvotes: 2
Views: 307
Reputation: 347332
As I see it, the major problem you have is here...
public void restart() {
// May return null and is only a snapshot of what's current within the components
// graphics buffer...
Graphics g = getGraphics();
Dimension d = getSize();
Color c = getBackground();
g.setColor(c);
g.fillRect(0,0,d.width,d.height);
// Every thing you just did will not be discard as when paintComponent
// is called...
repaint();
}
You should also be called super.paintComponent
as the first statement within your paintComponent
method
All painting should be done in your paintComponent
method.
Check out Painting in AWT and Swing for more details about the paint engine.
Basically, your controls are hiding your custom painting.
One of the most important aspects of OO is separation of responsibility. That is, each class should do one job (and do it well).
In your case, your HangMan
class was trying to manage the UI controls, custom painting and basic game rules...
The example blow separates the game rules/state into a model which is shared by the main view and the panel responsible for painting the state of the game....
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TestHangMan01 {
public static void main(String[] args) {
new TestHangMan01();
}
public TestHangMan01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Hangman());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class HangManModel {
public int youLose;
public int wrongGuess;
public String message;
public String theWord;
public StringBuffer guessWord;
private Set<ChangeListener> listeners;
public HangManModel() {
listeners = new HashSet<>(25);
}
public void setTheWord(String theWord) {
this.theWord = theWord;
guessWord = new StringBuffer(theWord.length());
while (guessWord.length() < theWord.length()) {
guessWord.append("_");
}
youLose = theWord.length();
wrongGuess = 0;
message = "";
fireStateChanged();
}
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
protected void fireStateChanged() {
if (listeners.size() > 0) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
public int getWrongGuess() {
return wrongGuess;
}
public String getMessage() {
return message;
}
public String getGuessWord() {
return guessWord.toString();
}
public void setMessage(String value) {
if (message == null ? value != null : !message.equals(value)) {
this.message = value;
fireStateChanged();
}
}
public void guess(char letter) {
if (!Character.isLetter(letter)) {
setMessage("Invalid character");
} else {
String temp = new String(guessWord);
if (temp.indexOf(letter) != -1) {
message = "Letter has already been guessed";
} else {
if (theWord.indexOf(letter) == -1) {
wrongGuess++;
if (wrongGuess == youLose) {
setMessage("You lose! The word was '" + theWord + "'" + "\nClick restart to try again.");
} else {
setMessage("You have " + (youLose - wrongGuess) + " guesses left.");
}
} else {
for (int i = 0; i < theWord.length(); i++) {
if (theWord.charAt(i) == letter) {
guessWord.setCharAt(i, letter);
}
}
temp = new String(guessWord);
if (temp.indexOf('_') == -1) {
setMessage("You win!");
} else {
setMessage("");
}
}
}
}
}
}
public class HangManPane extends JPanel implements ChangeListener {
private HangManModel model;
public HangManModel getModel() {
return model;
}
public void setModel(HangManModel value) {
if (model != value) {
if (model != null) {
model.removeChangeListener(this);
}
this.model = value;
if (model != null) {
model.addChangeListener(this);
}
repaint();
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
HangManModel model = getModel();
//(left, top, right, bottom)
g.drawLine(90, 250, 200, 250);
g.drawLine(125, 250, 125, 150);
g.drawLine(125, 150, 175, 150);
g.drawLine(175, 150, 175, 175);
if (model.getWrongGuess() > 0) { //head
g.drawOval(170, 175, 10, 12);
}
if (model.getWrongGuess() > 1) { //body
g.drawLine(175, 187, 175, 205);
}
if (model.getWrongGuess() > 2) { //left arm
g.drawLine(163, 185, 173, 190);
}
if (model.getWrongGuess() > 3) { //right arm
g.drawLine(177, 190, 187, 185);
}
if (model.getWrongGuess() > 4) { //left leg
g.drawLine(168, 220, 173, 205);
}
if (model.getWrongGuess() > 5) { //right leg
g.drawLine(177, 205, 182, 220);
}
g.drawString(model.getMessage(), 40, 290);
g.drawString(model.getGuessWord(), 40, 275);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
}
public class Hangman extends JPanel implements ActionListener {
public JButton restartButton;
public JButton playButton;
public JTextField userInput;
private HangManModel model;
public Hangman() {
setModel(new HangManModel());
setLayout(new BorderLayout());
userInput = new JTextField();
restartButton = new JButton("Restart");
playButton = new JButton("Play");
JPanel controls = new JPanel(new GridLayout(1, 4));
controls.add(restartButton);
controls.add(playButton);
controls.add(new JLabel("Enter guess: "));
controls.add(userInput);
add(controls, BorderLayout.NORTH);
userInput.addActionListener(this);
restartButton.addActionListener(this);
playButton.addActionListener(this);
HangManPane hangManPane = new HangManPane();
hangManPane.setModel(getModel());
add(hangManPane);
startGame();
}
public void setModel(HangManModel model) {
this.model = model;
}
public HangManModel getModel() {
return model;
}
public void actionPerformed(ActionEvent event) {
if (event.getSource() == restartButton) {
restart();
startGame();
}
if (event.getSource() == playButton || event.getSource() == userInput) {
analyzeGuess();
userInput.setText("");
repaint();
}
setVisible(true);
}
public void restart() {
startGame();
}
public void startGame() {
String[] wordArray = {"computer", "science", "java", "application", "programming", "university",
"homework", "assignment", "cactus", "flower", "button", "keyboard", "graphic", "interface",
"collegiate", "graduate", "headphones", "building", "radiator", "flora", "fauna", "suitcase",
"sweater", "television", "library", "elevator", "precidence", "ancient", "basketball", "bracket",
"alphabetical", "christmas", "hannukah"};
Random randomGenerator = new Random();
int randomInt = randomGenerator.nextInt(wordArray.length);
String theWord = new String(wordArray[randomInt]);
getModel().setTheWord(theWord);
userInput.setText("");
}
private void analyzeGuess() {
String userGuess = userInput.getText();
if (userGuess.trim().length() > 0) {
getModel().guess(userGuess.charAt(0));
}
}
}
}
Upvotes: 1