Good day!

hello! lately i've been working on a project of mine and im almost done. but right now i have a problem. in my hangman program i cant seem to make thing that hangs the hangman appear, it will only appera after ive clicked the check button. can anyone help me please? the code is below.

P.S.

I've already tried the:

public void paintComponent (Graphics g)
{
super.paintComponent(g);
g.setColor(Color.red);
g.drawLine(130,450,240,450);
g.drawLine(185,40,185,450);
g.drawLine(110,40,185,40);
g.drawLine(110,40,110,100);
}

using the code above the thing (that hangs the man) still wont appear when i execute the program.
any help is greatly appreciated :)

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Hangman extends JFrame implements ActionListener {

    // DECLARATIONS
    
    JLabel	inputL,
    		lettersL,
    		wordL;

    JTextField	inputTF,
    			lettersTF,
    			wordTF;

    JButton	checkB,
    		exitB;
    
    final String WORD[] = { "SPLINTER" , "MAGICAL" , "FUNDAMENTAL" , "ONYX" , "UNIVERSAL" 
    				, "MYSTERIOUS" , "QUAIL" , "DISCOVER" , "UNIQUE" , "OLYMPICS" };
    
    static int index;
    
    int chances = 6;
    
    char[] blanks,guess;
    
    String usedLetters = "";    
    
    public Hangman()
    {
    	JPanel thePanel = new JPanel();
    	thePanel.setBackground(Color.black);
    	
    	inputL = new JLabel("Enter a letter");
    	lettersL = new JLabel("Used Letters");
   		wordL = new JLabel("The Word");
 		
   		inputTF = new JTextField();
   		lettersTF = new JTextField(26);
   		wordTF = new JTextField(16);
   		
   		inputTF.setFont(new Font("Arial",Font.BOLD,20));
   		inputTF.setHorizontalAlignment(0);
   		lettersTF.setFont(new Font("Arial",Font.BOLD,20));
   		lettersTF.setEditable(false);
   		lettersTF.setHorizontalAlignment(JTextField.CENTER);
   		wordTF.setFont(new Font("Arial",Font.BOLD,20));
   		wordTF.setEditable(false);
   		wordTF.setHorizontalAlignment(JTextField.CENTER);
   		
   		String text = "";
    	for(int ctr=0 ; ctr < WORD[index].length() ; ctr++)
    		text = text + "_ ";
    	wordTF.setText(text);
    	blanks = text.toCharArray();
   		
   		checkB = new JButton("Check");
   		checkB.addActionListener(this);
   		
   		exitB = new JButton("EXIT");
   		exitB.addActionListener(this);
    	
    	Container pane = getContentPane();
    	pane.setLayout(new GridLayout(1,2,10,0));
    	
    	Container pane1 = new Container();
    	pane1.setLayout(new GridLayout(8,1,8,8));
    	pane1.add(wordL);
    	pane1.add(wordTF);
    	pane1.add(lettersL);
    	pane1.add(lettersTF);
   		pane1.add(inputL);
    	pane1.add(inputTF);
    	pane1.add(checkB,BorderLayout.EAST);
    	pane1.add(exitB,BorderLayout.SOUTH);
    	
    	pane.add(thePanel);
    	pane.add(pane1);
    	
    	setResizable(false);
    	setTitle("Hangman BETA VERSION");
    	setLocation(120,120);
    	setVisible(true);
    	setDefaultCloseOperation(EXIT_ON_CLOSE);
    	setSize(500,500);	
    }
    
    
    public void actionPerformed (ActionEvent e)
    {
    	Graphics g = getGraphics();
    	g.setColor(Color.red);
    	g.drawLine(130,450,240,450);
    	g.drawLine(185,40,185,450);
    	g.drawLine(110,40,185,40);
    	g.drawLine(110,40,110,100);
    	
    	if(e.getSource()==exitB)
    		
    		System.exit(0);
    		
    	else if(e.getSource()==checkB)
    	{
    		char letter;
    		String input;
    		Boolean correct = false;
    		
    		input = inputTF.getText();
    		letter = Character.toUpperCase( input.charAt(0) );
    		
    		if(input.equals(null))
    			
    			JOptionPane.showMessageDialog(null,"You Have to Enter Something!","ERROR",JOptionPane.WARNING_MESSAGE);  
			
			else if( input.length() != 1)
    			
    			JOptionPane.showMessageDialog(null,"ENTER A SINGLE CHARACTER!","ERROR",JOptionPane.WARNING_MESSAGE);
    			
    		else if(Character.isDigit(letter))
    			
    			JOptionPane.showMessageDialog(null,"ENTER A CHARACTER NOT A NUMBER","ERROR",JOptionPane.WARNING_MESSAGE);
    		
    		else
    		{
    			guess = WORD[index].toCharArray();
    			
    			for(int ctr =0 ; ctr < WORD[index].length() ; ctr++)
    			{
    				if( letter == guess[ctr] )
    				{
    					blanks[ctr*2]=guess[ctr]; 
    					correct = true;
    				}
    			}
    			
				if (!correct)
    			{
    				usedLetters = usedLetters + letter + " ";
    			
    				switch (chances)
    				{
   						case 1: g.drawArc(85,150,50,30,0,180); chances--; break;
   						case 2: g.drawLine(90,130,105,130); g.drawLine(115,130,130,130); chances--; break;
   						case 3: g.drawLine(70,230,150,230); chances--; break;
   						case 4: g.drawLine(110,350,70,400); g.drawLine(110,350,150,400); chances--; break;
   						case 5: g.drawLine(110,180,110,350); chances--; break;
    					case 6: g.drawOval(70,100,80,80); chances--; break;
					}
					
					if(chances==0)
					{
						JOptionPane.showMessageDialog(null,"GAMEOVER!\n The Word is " + WORD[index],"GAMEOVER!",JOptionPane.INFORMATION_MESSAGE);
						System.exit(0);
					}
    			
    			}
    		wordTF.setText(new String(blanks));
    		}
    		
    		lettersTF.setText(new String(usedLetters));
    		inputTF.setText("");
    			
    	}
    	
    }
	
    
    public static void main (String [] args)
    {	
    	
    	index = (int) ( ( Math.random() ) * 10 );
    	Hangman theFrame = new Hangman();
    	
    }
    
    
}

Recommended Answers

All 17 Replies

your the reason it won't draw is because your doing all of your drawing in your action listener, and it doesn't get called at the start of your program, so nothing gets drawn.

one way i see to solve the problem...

make a new boolean variable, i would call it something like startup and initially set it to true.
then surround everything in your action performed from if(e.getsourc()==exitB) to the end of the action listener with an if(!startup) block. and then in your constructor call checkB.doClick() then set startup to false

or...

for a shorter way put this:

Graphics g = getGraphics();
    	g.setColor(Color.red);
    	g.drawLine(130,450,240,450);
    	g.drawLine(185,40,185,450);
    	g.drawLine(110,40,185,40);
    	g.drawLine(110,40,110,100);

at the bottom of your constructor

thanks! ive tried the first way and it kinda works, but the second way wont work, the hanging thing just flashes for a milisecond and then it gets covered up by the black background

Use a separate panel for the painting, don't paint directly on the JFrame.

that is what i usually do... but i didn't think he wanted to rewrite his whole project to do that. it would require adding and removing much from his current implementation to account for another class.

He needn't rewrite the whole thing. Just a new panel where the drawing is to occur and use that graphic context to drawn on instead of the JFrame context.

By the way, be sure to dispose of a graphics context obtained with getGraphics() by calling dispose() on the reference when you are finished with it.

ok, sure i forgot about that... i usually extend JPanel so i can give it a functionality which would require rewriting his code. can't be right always oh well :D

Yes, extending a component and overriding paintComponent() is the usual and preferable way to do it and this code would certainly benefit from that (drag another window over the frame and see what happens to the hangman graphic), but at a minimum the existing code could draw to a panel (or label) reference with few changes.

Given the above discussion on using a panel to draw on and the fact that overriding paintComponent() really is the better way to go, I'd recommend the following, which is only a minor re-arrangement of your existing code (see comments on changes)

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Hangman extends JFrame implements ActionListener {

    // DECLARATIONS
    JLabel inputL,
      lettersL,
      wordL;
    JTextField inputTF,
      lettersTF,
      wordTF;
    JButton checkB,
      exitB;
    final String WORD[] = {"SPLINTER", "MAGICAL", "FUNDAMENTAL", "ONYX", "UNIVERSAL", "MYSTERIOUS", "QUAIL", "DISCOVER", "UNIQUE", "OLYMPICS"};
    static int index;
    int chances = 6;
    char[] blanks, guess;
    String usedLetters = "";
    // New reference to your hangman panel
    JPanel graphicPanel;

    public Hangman() {
        // override paintComponent to call the drawHangman() method
        graphicPanel = new JPanel() {
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                drawHangman(g);
            }
        };
        graphicPanel.setBackground(Color.black);

        inputL = new JLabel("Enter a letter");
        lettersL = new JLabel("Used Letters");
        wordL = new JLabel("The Word");

        inputTF = new JTextField();
        lettersTF = new JTextField(26);
        wordTF = new JTextField(16);

        inputTF.setFont(new Font("Arial", Font.BOLD, 20));
        inputTF.setHorizontalAlignment(0);
        lettersTF.setFont(new Font("Arial", Font.BOLD, 20));
        lettersTF.setEditable(false);
        lettersTF.setHorizontalAlignment(JTextField.CENTER);
        wordTF.setFont(new Font("Arial", Font.BOLD, 20));
        wordTF.setEditable(false);
        wordTF.setHorizontalAlignment(JTextField.CENTER);

        String text = "";
        for(int ctr = 0; ctr<WORD[index].length(); ctr++) {
            text = text+"_ ";
        }
        wordTF.setText(text);
        blanks = text.toCharArray();

        checkB = new JButton("Check");
        checkB.addActionListener(this);

        exitB = new JButton("EXIT");
        exitB.addActionListener(this);

        Container pane = getContentPane();
        pane.setLayout(new GridLayout(1, 2, 10, 0));

        Container pane1 = new Container();
        pane1.setLayout(new GridLayout(8, 1, 8, 8));
        pane1.add(wordL);
        pane1.add(wordTF);
        pane1.add(lettersL);
        pane1.add(lettersTF);
        pane1.add(inputL);
        pane1.add(inputTF);
        pane1.add(checkB, BorderLayout.EAST);
        pane1.add(exitB, BorderLayout.SOUTH);

        pane.add(graphicPanel);
        pane.add(pane1);

        setResizable(false);
        setTitle("Hangman BETA VERSION");
        setLocation(120, 120);
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(500, 500);
    }

    /** draws the hangman graphic */
    private void drawHangman(Graphics g) {
        // the gallows
        g.setColor(Color.red);
        g.drawLine(130, 450, 240, 450);
        g.drawLine(185, 40, 185, 450);
        g.drawLine(110, 40, 185, 40);
        g.drawLine(110, 40, 110, 100);

        // intentional switch fall-through to 
        // draw the man as chances decrease
        switch(chances) {
            case 0:
                g.drawArc(85, 150, 50, 30, 0, 180);
            case 1:
                g.drawLine(90, 130, 105, 130);
                g.drawLine(115, 130, 130, 130);
            case 2:
                g.drawLine(70, 230, 150, 230);
            case 3:
                g.drawLine(110, 350, 70, 400);
                g.drawLine(110, 350, 150, 400);
            case 4:
                g.drawLine(110, 180, 110, 350);
            case 5:
                g.drawOval(70, 100, 80, 80);
        }
    }

    public void actionPerformed(ActionEvent e) {

        if(e.getSource()==exitB) {
            System.exit(0);
        } else if(e.getSource()==checkB) {
            char letter;
            String input;
            Boolean correct = false;

            input = inputTF.getText();
            letter = Character.toUpperCase(input.charAt(0));

            if(input.equals(null)) {
                JOptionPane.showMessageDialog(null, "You Have to Enter Something!", "ERROR", JOptionPane.WARNING_MESSAGE);
            } else if(input.length()!=1) {
                JOptionPane.showMessageDialog(null, "ENTER A SINGLE CHARACTER!", "ERROR", JOptionPane.WARNING_MESSAGE);
            } else if(Character.isDigit(letter)) {
                JOptionPane.showMessageDialog(null, "ENTER A CHARACTER NOT A NUMBER", "ERROR", JOptionPane.WARNING_MESSAGE);
            } else {
                guess = WORD[index].toCharArray();

                for(int ctr = 0; ctr<WORD[index].length(); ctr++) {
                    if(letter==guess[ctr]) {
                        blanks[ctr*2] = guess[ctr];
                        correct = true;
                    }
                }

                if(!correct) {
                    usedLetters = usedLetters+letter+" ";

                    // update chances and repaint the panel
                    chances--;
                    graphicPanel.repaint();

                    if(chances==0) {
                        JOptionPane.showMessageDialog(null, "GAMEOVER!\n The Word is "+WORD[index], "GAMEOVER!", JOptionPane.INFORMATION_MESSAGE);
                        System.exit(0);
                    }
                }
                wordTF.setText(new String(blanks));
            }

            lettersTF.setText(new String(usedLetters));
            inputTF.setText("");
        }
    }

    public static void main(String[] args) {
        index = (int)((Math.random())*10);
        Hangman theFrame = new Hangman();
    }
}

(I did not correct or alter anything else in the code - just the graphics)

commented: useful information +1
graphicPanel = new JPanel() {
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                drawHangman(g);
            }
        };

i didn't know you could do that, cool, that makes some stuff a lot simpler for some of my projects

Yes, it's just providing an anonymous inner class implementation of JPanel on initialization. You have probably seen it before with action listeners, Comparators, Runnables that are being handed off to a thread, etc.

yes, but i haven't seen it used to override paintcomponent(), would it work with paint()? (i assume so)

Sure, it's not limited to specific methods, though if you are wanting to override quite a few or manage complex state, it is usually better to just go ahead and declare a normal inner class (or top-level if it would be useful outside the context of the containing class).

Often anonymous inner classes are used for "function objects" that specify a single method implementation, like actionPerformed() for a button listener. Such usage can be considered similar to function pointers in C++.

wow! thanks dude! im gonna go rewrite my code now =)

im gonna ask something off topic here, how can i add an option to play again? thanks!

well you could write a method that clears everything and chooses a new word

commented: thanks +1

thank you for helping me sciwizeh!

The graphics are very entertainment to all and with hollywood tstudio movies presents 3d graphics.
<snip false signature>

commented: Useless post and violation of rules regarding links in "fake signature". -2
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.