954,510 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Something about Graphics

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();
    	
    }
    
    
}
esy928
Light Poster
42 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

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

sciwizeh
Posting Pro in Training
457 posts since Jun 2008
Reputation Points: 77
Solved Threads: 23
 

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

esy928
Light Poster
42 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

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

Ezzaral
Posting Genius
Moderator
15,986 posts since May 2007
Reputation Points: 3,250
Solved Threads: 847
 

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.

sciwizeh
Posting Pro in Training
457 posts since Jun 2008
Reputation Points: 77
Solved Threads: 23
 

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.

Ezzaral
Posting Genius
Moderator
15,986 posts since May 2007
Reputation Points: 3,250
Solved Threads: 847
 

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

sciwizeh
Posting Pro in Training
457 posts since Jun 2008
Reputation Points: 77
Solved Threads: 23
 

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.

Ezzaral
Posting Genius
Moderator
15,986 posts since May 2007
Reputation Points: 3,250
Solved Threads: 847
 

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)

Ezzaral
Posting Genius
Moderator
15,986 posts since May 2007
Reputation Points: 3,250
Solved Threads: 847
 
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

sciwizeh
Posting Pro in Training
457 posts since Jun 2008
Reputation Points: 77
Solved Threads: 23
 

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.

Ezzaral
Posting Genius
Moderator
15,986 posts since May 2007
Reputation Points: 3,250
Solved Threads: 847
 

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

sciwizeh
Posting Pro in Training
457 posts since Jun 2008
Reputation Points: 77
Solved Threads: 23
 

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++.

Ezzaral
Posting Genius
Moderator
15,986 posts since May 2007
Reputation Points: 3,250
Solved Threads: 847
 

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

esy928
Light Poster
42 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

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

esy928
Light Poster
42 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

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

sciwizeh
Posting Pro in Training
457 posts since Jun 2008
Reputation Points: 77
Solved Threads: 23
 

thank you for helping me sciwizeh!

esy928
Light Poster
42 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

The graphics are very entertainment to all and with hollywood tstudio movies presents 3d graphics.

kimslov
Newbie Poster
1 post since Aug 2008
Reputation Points: 8
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You