paintComponent is stressing me out; Hangman programming project - java

Ok, so I have a programming project due in a few hours and I am close to finished. I can only paint certain parts of the hangman at a time, which is dependent on the amount of incorrect tries by the user. The teacher of my programming class requires the creation of the hangman drawing to be in a different class. The problem I'm having is sending over the number of incorrect tries to a class with the paintComponent.
if(updatedChallenge == challenge)
{
incorrectTries += 1;
}
challenge = updatedChallenge;
The challenge == updated challenge refers to the hidden word before the user's guess and the hidden word after the user's guess. If they are still equal that means the user made an incorrect choice. 1 gets added to the total number of incorrect tries.
Here is my other class:
class HangmanPicture extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.drawLine(250, 300, 300, 300); //Platform
g.drawLine(275, 300, 275, 200); //Pole
g.setColor(Color.YELLOW);
g.drawLine(275, 200, 350, 200); //Rope
g.drawLine(350, 200, 350, 225); //Noose
g.setColor(Color.CYAN);
g.drawOval(350, 225, 15, 15); //Head
g.drawLine(350, 230, 350, 260); //Torso
g.drawLine(350, 240, 340, 230); //Left Arm
g.drawLine(350, 240, 360, 230); // Right Arm
g.drawLine(350, 260, 330, 280); // Left Leg
g.drawLine(350, 260, 390, 280); // Right Leg
}
}
I want to put an if statement where each body part gets added after each incorrect try, which requires me to send the number of incorrect tries to the class. Whenever I try to send the number, it always somehow interferes with paintComponent
Any help would be greatly appreciated, I'm desperate. Thanks in advanced!

Since you are extending the JPanel class. We can add extra methods and fields to the class and use them where HangmanPicture is being used.
HangmanPicture panel = new HangmanPicture();
...
if(updatedChallenge == challenge)
{
panel.addIncorrectAttempt();
}
challenge = updatedChallenge;
class HangmanPicture extends JPanel
{
private int incorrectAttempts = 0;
// Add one to counter
public void addIncorrectAttempt(){
incorrectAttempte++;
}
// Get how many times the player entered an incorrect number
public int getIncorrectAttempts(){
return incorrectAttempts;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
if( incorrectAttempts >= 1 ){
g.drawLine(250, 300, 300, 300); //Platform
}
if( incorrectAttempts >= 2 ){
g.drawLine(275, 300, 275, 200); //Pole
}
}
}

Related

Plotting Logarithmic and Exp graph in Java

I am doing my coursework on Java and I am stuck in doing the graphs for 3 functions. X-x^2, ln(x-1)-1 and e^x-3x.
I have already tried to set up JFrame with axis and even code for x-x^2 that plots graph for that function.
int x,y;
int ax,by;
String s="deba";
String se ="deba";
public Plotfunct1(){
setTitle("Function graph");
setSize(900,700);
setLayout(null);
setVisible(true);
setResizable(false);
x = 30;
y = 300;
}
#Override
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.drawString("Y", 310, 40);
g.drawString("Y'", 310, 600);
g.drawString("X", 30, 314);
g.drawString("X'", 600, 314);
if(x==300&&y==300){
g.drawString("Origin(0,0)", 310, 314);
}
g.drawLine(300, 30, 300, 600);
g.drawLine(30,300,600,300);
if(x>599||y<40){
x = 30;
y=300;
}
if(x<600&&y>30&&y!=600){
ax = x-300;
by = y-300;
ax++;
by = (int) (.095*(ax-Math.pow(ax,2)));
x=300+ax;
y=300-by;
}
g.fillOval(x, y, 3, 3);
repaint();
}
}
I need to plot the last 2 functions I have tried everything that I could come up with changing the Math.pow to Math.log but then I just get one line
Have you tried using Polygons?
I dont have experience with the Graphics class, but seems like fillOval() only draws circles, it does not apply for logarithmic functions.
Check this answer. You can add points to the graph using addPoint() on the Polygon, then draw the polygon on the Graphic using drawPolyline(). All you have to do is adjust the formula.

Bouncing multiple lines with fixed coordinates off walls in java graphics [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I want to store the fixed coordinates and then increment the coordinates until they reache the edge of the screen.
Here's my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Name extends JPanel
{
int x, y, w, h, xdir, ydir;
public Name ()
{
}
public void paintComponent (Graphics g)
{
super.paintComponent (g);
g.drawLine(110+x, 300+y, 95+x, 400+y);
g.drawLine(110, 300, 123, 350);
g.drawLine(135, 300, 123, 350); //M
g.drawLine(135, 300, 150, 400);
g.drawOval (150, 300, 15, 15); // i
g.fillOval (150, 300, 15, 15);
g.drawLine (155, 320, 155, 400);
g.drawLine (172, 300, 172, 400); // k
g.drawLine (172, 350, 185, 300);
g.drawLine (172, 350, 185, 400);
g.drawLine (190, 360, 265, 360); // e
g.drawArc (190, 325, 75, 75, 360, 180);
g.drawArc (190, 330, 75, 75, 168, 180);
w = getSize ().width;
h = getSize ().height;
xdir = 1;
ydir = 1;
x = x + xdir;
y = y+ ydir;
if (x > w || x < 0)
{
xdir = -1 * xdir;
}
if (y > h || y < 0)
{
ydir = -1 * ydir;
}
repaint ();
MyLib.delay (25);
} // paint method
public static void main (String[] args)
{
JFrame frame = new JFrame ("NameBounce");
frame.getContentPane ().add (new Name ());
frame.setSize (500, 500);
frame.setVisible (true);
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
} // main method
} // Name class
I've tried storing the coordinates into array lists but had no luck.
I've been trying to avoid hard coding the entire program.
Use something like Path2D to define the shapes you want to draw (you can draw all the letters within a single Path2D)
Use a AffineTransform to translate the location of the Graphics and Graphics2D#draw to physically paint the Path2D
Use a Swing Timer to schedule a regular call back within which you can update the position of the Path2D and call repaint on the component to trigger an update
See
Concurrency in Swing
How to use Swing Timers
2D Graphics
for more details
Don't call Thread.sleep or any other blocking process within the paintComponent method (or from within the context of the Event Dispatching Thread) as this will prevent the EDT from updating the screen.
Make sure you are creating/updating your UI only from within the context of the EDT, see Initial Threads for more details

Printing Java shapes with a delay

I am trying to create a program that solves the popular Towers of Hanoi game. I have succeeded in printing the disks and pegs, but I want the disks to print with a delay. For example, I want disk 7 to print, then disk 6 to print 1 second later. I tried this by putting it to sleep, but all it does is delay the whole frame from displaying, how do I make it display the shape with a delay. I have attached my code, thanks for any help!
package towersofhanoi;
import javax.swing.*;
import java.awt.*;
/*g.fillOval(60 = horizontal distance , 540= vertical distance, 400 = width, 60 = height) */
public class TowersOfHanoi extends JPanel {
public static void main(String[]args){
//Print the shapes and frame
TowersOfHanoi drawRectangle = new TowersOfHanoi();
JFrame frame = new JFrame("Towers of Hanoi");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(drawRectangle);
frame.setSize(1250, 800);
frame.setVisible(true);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Color pegs = new Color (251, 129, 56);
g.setColor(pegs);
//peg 1
g.fillRect(250, 300, 25, 450);
//peg 2
g.fillRect(600, 300, 25, 450);
//peg 3
g.fillRect(950, 300, 25, 450);
//bottom
g.fillRect(200, 700, 825, 50);
//create a color for circles
Color circles = new Color (176,56, 251);
//cirle 7 (Labeled from bottom to top)
g.setColor(circles);
g.fillOval(60, 640, 400, 60);
g.setColor(Color.BLACK);
g.drawOval(60, 640, 400, 60);
try {
Thread.sleep(1000);
}
catch (InterruptedException ie) {
}
//circle 6
g.setColor(circles);
g.fillOval(85, 580, 350, 60);
g.setColor(Color.BLACK);
g.drawOval(85, 580, 350, 60);
try {
Thread.sleep(1000);
}
catch (InterruptedException ie) {
}
//circle 5
g.setColor(circles);
g.fillOval(110, 520, 300, 60);
g.setColor(Color.BLACK);
g.drawOval(110, 520, 300, 60);
//circle 4
g.setColor(circles);
g.fillOval(135, 465, 250, 55);
g.setColor(Color.BLACK);
g.drawOval(135, 465, 250, 55);
//circle 3
g.setColor(circles);
g.fillOval(160, 420, 200, 45);
g.setColor(Color.BLACK);
g.drawOval(160, 420, 200, 45);
//circle 2
g.setColor(circles);
g.fillOval(185, 380, 150, 40);
g.setColor(Color.BLACK);
g.drawOval(185, 380, 150, 40);
//circle 1
g.setColor(circles);
g.fillOval(210, 345, 100, 35);
g.setColor(Color.BLACK);
g.drawOval(210, 345, 100, 35);
}
}
My recommendation
separate out drawing in paintComponent() into the 3 constitute parts, these were previously separated by sleep statements
Use state inside the TowersOfHanoi object to control what should be drawn, I've used a simple counter
Use javax.swing.Timer to update the counter and request a repaint.
Notes
You cannot sleep on the UI thread. Swing is single threaded and this would stop events being processed.
javax.swing.Timer automatically fires the callback you give it on the UI thread.
paintComponent() can be called multiple times if windows are resized etc, therefore it is important to make it independent, hence my use of a counter.
Working example
public class TowersOfHanoi extends JPanel {
private int clock = 0;
private Color circles = new Color(176, 56, 251);
public static void main(String[] args) {
// Print the shapes and frame
TowersOfHanoi drawRectangle = new TowersOfHanoi();
JFrame frame = new JFrame("Towers of Hanoi");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(drawRectangle);
frame.setSize(1250, 800);
frame.setVisible(true);
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
drawRectangle.nextFrame();
drawRectangle.repaint();
}
});
timer.setRepeats(true);
timer.start();
}
public void nextFrame() {
clock++;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
frame1(g);
if (clock >= 1) {
frame2(g);
}
if (clock >= 2) {
frame3(g);
}
}
private Color frame1(Graphics g) {
Color pegs = new Color(251, 129, 56);
g.setColor(pegs);
// peg 1
g.fillRect(250, 300, 25, 450);
// peg 2
g.fillRect(600, 300, 25, 450);
// peg 3
g.fillRect(950, 300, 25, 450);
// bottom
g.fillRect(200, 700, 825, 50);
// create a color for circles
// cirle 7 (Labeled from bottom to top)
g.setColor(circles);
g.fillOval(60, 640, 400, 60);
g.setColor(Color.BLACK);
g.drawOval(60, 640, 400, 60);
return circles;
}
private void frame2(Graphics g) {
// circle 6
g.setColor(circles);
g.fillOval(85, 580, 350, 60);
g.setColor(Color.BLACK);
g.drawOval(85, 580, 350, 60);
}
private void frame3(Graphics g) {
// circle 5
g.setColor(circles);
g.fillOval(110, 520, 300, 60);
g.setColor(Color.BLACK);
g.drawOval(110, 520, 300, 60);
// circle 4
g.setColor(circles);
g.fillOval(135, 465, 250, 55);
g.setColor(Color.BLACK);
g.drawOval(135, 465, 250, 55);
// circle 3
g.setColor(circles);
g.fillOval(160, 420, 200, 45);
g.setColor(Color.BLACK);
g.drawOval(160, 420, 200, 45);
// circle 2
g.setColor(circles);
g.fillOval(185, 380, 150, 40);
g.setColor(Color.BLACK);
g.drawOval(185, 380, 150, 40);
// circle 1
g.setColor(circles);
g.fillOval(210, 345, 100, 35);
g.setColor(Color.BLACK);
g.drawOval(210, 345, 100, 35);
}
}
Have you tried using Caldender() or System.currentTimeMillis()? If you do, you can get the current time. After you have gotten the time, do a while loop to check what the time is now. When you do LastTime - Now, to check how much time has passed.
This code is not tested, (But it should work).
long lastTime = System.currentTimeMillis();
while(true){
long now = System.currentTimeMillis();
if(lastTime - now == [YOUR PREFFERD WAITING TIME IN MS]){
break;
}
}
And now draw your graphics.
You should probably restructure you code so that paint component draws the current state of the system of pegs and rings. Then use a Swing timer to call a method that moves the state of the system then calls repaint().

Key Listener not working

public void paint (Graphics g)
{
bufferGraphics.setColor (Color.black);
bufferGraphics.clearRect (0, 0, dim.width, dim.width);
while (input != KeyEvent.VK_SPACE)
{
bufferGraphics.fillRect (0, 0, dim.width, dim.height);
}
bufferGraphics.drawImage (track, 0, 0, dim.width, dim.height, this);
bufferGraphics.setFont (new Font ("Calibri", Font.PLAIN, 25));
bufferGraphics.drawString ("Level: " + level, 30, 30);
bufferGraphics.drawImage (car, 620, myCarY, 70, 120, this);
bufferGraphics.drawImage (opponent, 415, oppCarY, 70, 120, this);
move ();
This is the code as it stands now. When executed, I get a frozen blank window that cannot even be closed.
Your issue is in your if statement.
if(run = false)
will never execute, as assignment returns the value being assigned (e.g. false).
You need to change your = to an ==.
You may also want to change your infinite for loop to a while loop, something like
while(input != KeyEvent.VK_SPACE) {
}
Also make sure that your KeyListener is being added to your class (in ctor)
addKeyListener(new MyKeyListener())
I just tested the code, and it worked.

Java House Applet

So I'm just starting with Applets and I am making a house with an open door and 2 open windows when the applet loads. When you click these windows or door then they will shut. My question though is what do I need to do to re-open these windows doors. I figure I need to set the Boolean variables to False somehow and repaint. Where would I do this. I don't need you guys to write the code for me, I just want to know what I should do.
Thanks ahead of time,
Rick
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
/**
Rick Armstrong
Chapter 14 - House Applet
*/
public class HouseApplet extends Applet {
boolean leftWin, rightWin, door;
public void init()
{
leftWin = false;
rightWin = false;
door = false;
setBackground(Color.white);
addMouseListener(new MyMouseListener());
}
public void paint(Graphics g)
{
super.paint(g);
// Draw the house.
g.setColor(Color.black);
g.drawRect(100, 100, 200, 100);
// Draw the roof
g.drawLine(80, 100, 320, 100);
g.drawLine(80, 100, 200, 40);
g.drawLine(200, 40, 320, 100);
// Draw the left window open.
g.fillRect(120, 130, 40, 40);
// Draw the right window open.
g.fillRect(240, 130, 40, 40);
// Draw the door open.
g.fillRect(180, 130, 40, 70);
if (leftWin) {
// Draw the left window closed.
g.setColor(Color.white);
g.fillRect(120, 130, 40, 40);
g.setColor(Color.black);
g.drawRect(120, 130, 40, 40);
g.drawLine(140, 130, 140, 170);
g.drawLine(120, 150, 160, 150);
}
if (rightWin) {
// Draw the right window closed.
g.setColor(Color.white);
g.fillRect(240, 130, 40, 40);
g.setColor(Color.black);
g.drawRect(240, 130, 40, 40);
g.drawLine(260, 130, 260, 170);
g.drawLine(240, 150, 280, 150);
}
if (door) {
// Draw the door closed.
g.setColor(Color.white);
g.fillRect(180, 130, 40, 70);
g.setColor(Color.black);
g.drawRect(180, 130, 40, 70);
g.fillOval(210, 165, 07, 07);
}
}
private class MyMouseListener implements MouseListener
{
public void mousePressed(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
int currentx = e.getX();
int currenty = e.getY();
boolean WindowLeft = (currentx >= 120 && currentx < 160 && currenty >= 130 && currenty <= 170);
if (WindowLeft)
{
leftWin = true;
repaint();
}
boolean WindowRight = (currentx >= 240 && currentx < 280 && currenty >= 130 && currenty <= 170);
if (WindowRight)
{
rightWin = true;
repaint();
}
boolean Door = (currentx >= 180 && currentx < 220 && currenty >= 40 && currenty <= 200);
if (Door)
{
door = true;
repaint();
}
else;
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
}
Maybe I'm misunderstanding the question, but why are you always setting the values to true in the event handler?
If you want a toggling behavior, you could simply write: value = !value and then repaint.
Since you initially set your value to false, the next click would set it to true, the next to false, etc. etc.
For example:
if (WindowLeft)
{
leftWin = !leftWin;
repaint();
}
Note that it is possible for you to cause sort of a "race condition" by clicking faster than the framework has a chance to update the view, but this is usually not a problem for initial problem.
BTW: In terms of readability, consider naming your variables in a way that conveys their meaning. For example, is the naming door evocative of a boolean? not really. but doorOpen is, and it helps interpret the meaning of the variable and its transitions.
if (WindowRight)
{
rightWin = false;
repaint();
}
else {
rightWin = true;
repaint();
}
try the above. When you click inside the window, it closes otherwise it opens

Categories

Resources