My problem is essentially creating a physics engine with a few different scenarios. I would like to consolidate the different scenarios into one window by having buttons that run each individually. The frame works properly and the buttons show up and can be pressed; however, that print line in the pain method is never happening and from there I concluded that paint is not being called even after repaint is. I understand that they are not the same but I don't understand why paint isn't being accessed in this instance compared to others.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import javax.swing.JButton;
public class PhysicsEngine extends JPanel{
double x ,y;
JFrame frame;
JPanel pan;
JButton b1;
JButton b2;
JButton b3;
JButton b4;
JButton b5;
public static void main(String[] args){
PhysicsEngine gui = new PhysicsEngine();
}
public PhysicsEngine(){
frame = new JFrame("Ball Engine");
pan = new JPanel();
frame.add(pan);
b1 = new JButton("1");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event){
try{
startFirst();
}
catch(InterruptedException exception){}
}
});
pan.add(b1);
b2 = new JButton("2");
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
try{
startSecond();
}
catch(InterruptedException exception){}
}
});
pan.add(b2);
b3 = new JButton("3");
b3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
try{
startThird();
}
catch(InterruptedException exception){}
}
});
pan.add(b3);
b4 = new JButton("4");
b4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
try{
startFourth();
}
catch(InterruptedException exception){}
}
});
pan.add(b4);
b5 = new JButton("5");
b5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
try{
startFifth();
}
catch(InterruptedException exception){}
}
});
pan.add(b5);
frame.setSize(600, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
super.paint(g);
System.out.println(""+y);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval((int)x, (int)y, 30, 30);
}
public void startFirst() throws InterruptedException{
x = 300;
for(int t = 1;;t++){
//xPos= 0*t*t + 0*t + 300 this is constant at 300
if(y>=615) break; //stops the loop when the ball is off the screen
y = .1*t*t + 0*t + 80; //parametric equation for y
repaint();
Thread.sleep(10);
}
}
public void startSecond() throws InterruptedException{
x = 300;
for(int t = 1;;t++){
//xPos= 0*t*t + 0*t + 300 this is constant at 300
if(y>=615) break; //stops the loop when the ball is off the screen
y = .1*t*t - 10*t + 550; //parametric equation for y
repaint();
Thread.sleep(10);
}
}
public void startThird() throws InterruptedException{
for(int t = 1;;t++){
if(y>=615||x>=615) break; //stops the loop when the ball is off the screen
y = .1*t*t - 10*t + 550; //parametric equation for y
x = 0*t*t + 5*t + 50; //parametric equation for x
repaint();
Thread.sleep(10);
}
}
public void startFourth() throws InterruptedException{
for(int t = 1;;t++){
//xPos= 0*t*t + 0*t + 300 this is constant at 300
if(y>=615||x>=615) break; //stops the loop when the ball is off the screen
y = t*t*t + 50; //given parametric equation for y
x = t - 4; //given parametric equation for x
repaint();
Thread.sleep(10);
}
}
public void startFifth() throws InterruptedException{
for(int t = 1;t<500 /* goes for 5 seconds */;t++){
y = 200*Math.sin(t) + 300; //given parametric equation for y
x = 200*Math.cos(t) + 300; //given parametric equation for x
repaint();
Thread.sleep(10);
}
}
}
The basic problem is you are overriding the paint() method of the PhysicsEngine class. But you never add an instance of this class to the frame.
However, the bigger problem is the structure of your class. Your main class should not be extending a JPanel just so you can create a JFrame. The logic for creating the frame should be in the main() method and then your PysicsEngine panel should contain all the components you want to build for your frame. Also, custom painting should be done by overriding the paintComponent(...) method, not the paint() method.
Read the section from the Swing tutorial on Custom Painting for basic painting information and demos.
Then you can look at other sections in the tutorial for a better way to structure your code. For example the ButtonDemo code found in the How to Use Buttons tutorial will show you how to extend a JPanel and add buttons to it.
repaint() stores a request for refreshing a component, request that will be executed by the GUI thread later on. But a component will be refreshed only if it is visible on screen, alas your PhysicsEngine class doesn't seem to be used as a visible component in some visible GUI hierarchy.
Your paint method should be paintComponent and also should call the paintComponent method of super class.
And you don't add the PhysicsEngine JPanel into the JFrame, and it is very bad approach to create a JFrame in the constructor of JPanel subclass. I create a JFrame in the main method and create a object of PhysicsEngine (JPanel Subclass) and add it into the JFrame. I add the buttons by using this which reference to the PhysicsEngine (JPanel subclass) object.
Here is the working code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JButton;
public class PhysicsEngine extends JPanel {
double x, y;
JPanel pan;
JButton b1;
JButton b2;
JButton b3;
JButton b4;
JButton b5;
public static void main(String[] args) {
JFrame frame = new JFrame("Ball Engine");
PhysicsEngine gui = new PhysicsEngine();
frame.add(gui, BorderLayout.CENTER);
frame.setSize(600, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public PhysicsEngine() {
b1 = new JButton("1");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
try {
startFirst();
} catch (InterruptedException exception) {
}
}
});
this.add(b1);
b2 = new JButton("2");
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startSecond();
} catch (InterruptedException exception) {
}
}
});
this.add(b2);
b3 = new JButton("3");
b3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startThird();
} catch (InterruptedException exception) {
}
}
});
this.add(b3);
b4 = new JButton("4");
b4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startFourth();
} catch (InterruptedException exception) {
}
}
});
this.add(b4);
b5 = new JButton("5");
b5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startFifth();
} catch (InterruptedException exception) {
}
}
});
this.add(b5);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("" + y);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval((int) x, (int) y, 30, 30);
}
public void startFirst() throws InterruptedException {
x = 300;
for (int t = 1;; t++) {
// xPos= 0*t*t + 0*t + 300 this is constant at 300
if (y >= 615)
break; // stops the loop when the ball is off the screen
y = .1 * t * t + 0 * t + 80; // parametric equation for y
repaint();
Thread.sleep(10);
}
}
public void startSecond() throws InterruptedException {
x = 300;
for (int t = 1;; t++) {
// xPos= 0*t*t + 0*t + 300 this is constant at 300
if (y >= 615)
break; // stops the loop when the ball is off the screen
y = .1 * t * t - 10 * t + 550; // parametric equation for y
repaint();
Thread.sleep(10);
}
}
public void startThird() throws InterruptedException {
for (int t = 1;; t++) {
if (y >= 615 || x >= 615)
break; // stops the loop when the ball is off the screen
y = .1 * t * t - 10 * t + 550; // parametric equation for y
x = 0 * t * t + 5 * t + 50; // parametric equation for x
repaint();
Thread.sleep(10);
}
}
public void startFourth() throws InterruptedException {
for (int t = 1;; t++) {
// xPos= 0*t*t + 0*t + 300 this is constant at 300
if (y >= 615 || x >= 615)
break; // stops the loop when the ball is off the screen
y = t * t * t + 50; // given parametric equation for y
x = t - 4; // given parametric equation for x
repaint();
Thread.sleep(10);
}
}
public void startFifth() throws InterruptedException {
for (int t = 1; t < 500 /* goes for 5 seconds */; t++) {
y = 200 * Math.sin(t) + 300; // given parametric equation for y
x = 200 * Math.cos(t) + 300; // given parametric equation for x
repaint();
Thread.sleep(10);
}
}
}
Related
I have a situation where I'm moving a ball. However, after struggling with the queue that repaint() places paintComponent(Graphics g) in. I resorted to using paintImmediately. The problem now is that without access to super.paintComponent(g), I don't know how to clear the canvas each time before I paint. So one possible answer to my question would be a way to clear the canvas by itself. I also found that Threads could be a possible solution but after a great many attempts to implement that idea, I still don't understand that so if someone could show correct implementation for that I would be very grateful.
Here is my code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JButton;
public class PhysicsEngine extends JPanel {
double x, y;
JPanel pan;
JButton b1;
JButton b2;
JButton b3;
JButton b4;
JButton b5;
public static void main(String[] args) {
JFrame frame = new JFrame("Ball Engine");
PhysicsEngine gui = new PhysicsEngine();
frame.add(gui, BorderLayout.CENTER);
frame.setSize(600, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public PhysicsEngine() {
b1 = new JButton("1");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
try {
startFirst();
} catch (InterruptedException exception) {
}
}
});
this.add(b1);
b2 = new JButton("2");
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startSecond();
} catch (InterruptedException exception) {
}
}
});
this.add(b2);
b3 = new JButton("3");
b3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startThird();
} catch (InterruptedException exception) {
}
}
});
this.add(b3);
b4 = new JButton("4");
b4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startFourth();
} catch (InterruptedException exception) {
}
}
});
this.add(b4);
b5 = new JButton("5");
b5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
startFifth();
} catch (InterruptedException exception) {
}
}
});
this.add(b5);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("" + y);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval((int) x, (int) y, 30, 30);
}
public void startFirst() throws InterruptedException {
x = 300;
y = 80;
// xPos= 0*t*t + 0*t + 300 this is constant at 300
for(int t = 1; t<70;t++){
y = .1 * t * t + 0 * t + 80; // parametric equation for y
repaint();
paintImmediately((int)x, (int)y, 30, 30);
Thread.sleep(10);
}
}
public void startSecond() throws InterruptedException {
x = 300;
y = 550;
for (int t = 1;t<150; t++) {
// xPos= 0*t*t + 0*t + 300 this is constant at 300
y = .1 * t * t - 15 * t + 550; // parametric equation for y
repaint();
paintImmediately((int)x, (int)y, 30, 30);
Thread.sleep(10);
}
}
public void startThird() throws InterruptedException {
y = 550;
x = 50;
for (int t = 1;t<150; t++) {
y = .1 * t * t - 15 * t + 550; // parametric equation for y
x = 0 * t * t + 3 * t + 50; // parametric equation for x
repaint();
paintImmediately((int)x, (int)y, 30, 30);
Thread.sleep(10);
}
}
public void startFourth() throws InterruptedException {
y = 50;
x = -4;
for (int t = 1;t<110; t++) {
// xPos= 0*t*t + 0*t + 300 this is constant at 300
y = .001*t * t * t + 50; // given parametric equation for y
x = t - 4; // given parametric equation for x
repaint();
paintImmediately((int)x, (int)y, 30, 30);
Thread.sleep(10);
}
}
public void startFifth() throws InterruptedException {
for (int t = 1; t < 130 /* goes for 1.5 seconds */; t++) {
y = 200 * Math.sin(.05*t) + 300; // given parametric equation for y
x = 200 * Math.cos(.05*t) + 300; // given parametric equation for x
repaint();
paintImmediately((int)x, (int)y, 30, 30);
Thread.sleep(10);
}
}
}
Your problem isn't the "paint queue", it's the fact that you're violating the single threaded nature of the API, by calling Thread.sleep within the context of the EDT.
Instead of using for-loops with Thread.sleep in them, you should make use of a Swing Timer which updates the state of the variables paintComponent relies on (and call repaint)
Swing Timer can be thought of a pseudo loop, whose ActionListener is called within the context of the EDT, making it safe to update the UI from
Start by having a look at Concurrency in Swing and How to Use Swing Timers for more details
As a conceptual example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private PhysicsPane physicsPane;
public TestPane() {
physicsPane = new PhysicsPane();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
JButton b1 = new JButton("1");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
startFirst();
}
});
this.add(b1, gbc);
this.add(physicsPane, gbc);
}
protected void startFirst() {
physicsPane.startFirst();
}
}
public class PhysicsPane extends JPanel {
private Timer timer;
private double xPos, yPos;
private int tick;
public PhysicsPane() {
setBackground(Color.BLUE);
}
protected void stopTimer() {
if (timer == null) {
return;
}
timer.stop();
timer = null;
}
public void startFirst() {
stopTimer();
xPos = 300;
yPos = 500;
tick = 0;
timer = new Timer(10, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (tick >= 150) {
stopTimer();
return;
}
yPos = .1 * tick * tick - 15 * tick + 550;
tick++;
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.fillOval((int) xPos, (int) yPos, 30, 30);
g2d.dispose();
}
}
}
so im given a working code as below, but then i have to convert it to use runnable interface
package lab12;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class MultiThreaded2 extends JFrame implements ActionListener {
public static final int WIDTH = 600;
public static final int HEIGHT = 400;
public static final int FILL_WIDTH = 600;
public static final int FILL_HEIGHT = 400;
public static final int SQUARE_SIZE = 10;
public static final int PAUSE = 100; // milliseconds
private JPanel box;
public static void main(String[] args) {
MultiThreaded2 gui = new MultiThreaded2();
gui.setVisible(true);
}
public MultiThreaded2() {
setSize(WIDTH, HEIGHT);
setTitle("Threaded Fill Demo");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
box = new JPanel();
add(box, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
JButton startButton = new JButton("Start");
startButton.addActionListener(this);
buttonPanel.add(startButton);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(this);
buttonPanel.add(stopButton);
add(buttonPanel, BorderLayout.SOUTH);
}
public void run() {
Graphics g = box.getGraphics();
int count = 0;
for (int y = 0; y < FILL_HEIGHT; y = y + SQUARE_SIZE) {
for (int x = 0; x < FILL_WIDTH; x = x + SQUARE_SIZE) {
if (count % 2 == 0) {
g.setColor(Color.red);
g.fillRect(x, y, SQUARE_SIZE, SQUARE_SIZE);
} else {
g.setColor(Color.blue);
g.drawRect(x, y, SQUARE_SIZE, SQUARE_SIZE);
}
try {
Thread.sleep(PAUSE);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count++;
}
}
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Start")) {
SecondThread secondThread = new SecondThread();
secondThread.start();
} else if (e.getActionCommand().equals("Stop")) {
System.exit(0);
}
}
private class SecondThread extends Thread {
public void run() {
Graphics g = box.getGraphics();
int count = 0;
for (int y = 0; y < FILL_HEIGHT; y = y + SQUARE_SIZE) {
for (int x = 0; x < FILL_WIDTH; x = x + SQUARE_SIZE) {
if (count % 2 == 0) {
g.setColor(Color.red);
g.fillRect(x, y, SQUARE_SIZE, SQUARE_SIZE);
} else {
g.setColor(Color.blue);
g.drawRect(x, y, SQUARE_SIZE, SQUARE_SIZE);
}
try {
Thread.sleep(PAUSE);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count++;
}
}
}
}
}
i understand that i must do something tot he public class secondthread yeah? but i dont know how to convert it to runnable since everything is working already.
i tried deleting the "extends thread" and insert " implements runnable" but that just gives me error. adding both "extends thread" and "implements runnable" works but i doubt thats what i had to do
It's kind of hard for anybody to tell you what an error message means if you don't tell us what the error message said, but here's a guess:
If you do nothing else but change SecondThread extends Thread to SecondThread implements Runnable, then secondThread.start() isn't going to compile because your SecondThread class does not define a start() method.
So, given a ... implements Runnable object, how do you get a thread to run it?
I suggest you spend some time with the Java Concurrency tutorial. https://docs.oracle.com/javase/tutorial/essential/concurrency/
The answer to my question is right near the beginning.
I was just wondering how I could manipulate buttons in java to make a bouncing ball stop, and then start. I tried writing an if else statement with a command to start the thread, and a command to stop it. However, that did not work. Could anyone possibly help me? Here is my code:
package javaapplication1;
import java.awt.*;
import java.applet.*;
import java.applet.Applet;
import java.awt.event.*;
public class BouncingBallOriginal extends Applet implements Runnable, ActionListener
{
Thread t=new Thread(this); /* declare and initialize a new thread */
int x = 0;
int y = 0;
int countX = 0;
int countY = 0;
Button button1; //space bar
Button button2;
public void init()
{
setSize(600,350);
t.start(); /* starts the thread */
setBackground(Color.blue);
button1 = new Button("Button 1");
add(button1);
button1.addActionListener(this);
button2 = new Button("Button 2");
add(button2);
button2.addActionListener(this);
}
private void incrementX() { x += 10; }
private void decrementX() { x -= 10; }
private void incrementY() { y += 10; }
private void decrementY() { y -= 10; }
public void run()
{
try
{
for(int i = 1; i > 0; i++)
{
Thread.sleep(200);
repaint();
}
}
catch(InterruptedException e)
{
//do nothing!
}
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == button1)
{
System.out.println("Button 1 was pressed");
}
else
{
System.out.println("Button 2 was pressed");
}
}
public void paint(Graphics g)
{
g.setColor(Color.yellow);
g.fillOval(x, y, 20, 20);
if(countX< (getSize().width / 10) - 1)
{
incrementX();
countX++;
}
if(countX >= (getSize().width / 10) - 1)
{
decrementX();
countX++;
}
if(countX >= (getSize().width / 5) - 2)
{
countX=0;
}
if(countY < (getSize().height / 10) - 1)
{
incrementY();
countY++;
}
if(countY >= (getSize().height / 10) - 1)
{
decrementY();
countY++;
}
if(countY >= (getSize().height / 5) - 2)
{
countY=0;
}
}
}
a way that you can do this is
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class BallControl extends JPanel {
private Ball ball = new Ball();
private JButton jbtSuspend = new JButton("Suspend");
private JButton jbtResume = new JButton("Resume");
private JScrollBar jsbDelay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(jbtSuspend);
panel.add(jbtResume);
// Add ball and buttons to the panel
ball.setBorder(new javax.swing.border.LineBorder(Color.red));
jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
ball.setDelay(jsbDelay.getMaximum());
setLayout(new BorderLayout());
add(jsbDelay, BorderLayout.NORTH);
add(ball, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
// Register listeners
jbtSuspend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ball.suspend();
}
});
jbtResume.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ball.resume();
}
});
jsbDelay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
ball.setDelay(jsbDelay.getMaximum() - e.getValue());
}
});
}
}
Forget about thread if you are talking about moving your objects. You moving your ball by changing its positions by a certain value lets call it speed. The way you should stop your ball is setting its speed to zero when a key is pressed instead of stopping the thread.
i have drawn a graph and placed a 20*20 pixel box in it and i am trying to move the box around with a bunch of buttons. the trouble is, i cant seem to change the X-axis and Y-axis values of the box from within the action listener. this is my first graphics application, help!
GrapMain.java
import java.awt.BorderLayout;
import javax.swing.JFrame;
import java.awt.Color;
import javax.swing.JTextField;
public class GraphMain {
public static void main(String [] args){
Display nashDisplay = new Display();
nashDisplay.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Graph.java
import java.awt.*;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Graph extends JPanel {
int x = 5, y = 100;
Graph (int x, int y){
this.x = x;
this.y = y;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.WHITE);
//horizontal lines
g.setColor(Color.RED);
for (int height=20; height<200; height+=20){
g.drawLine(5, height, 480, height);
}
//verticle lines
g.setColor(Color.RED);
for (int height=5; height<400; height+=20){
g.drawLine(height,200,height,10);
}
//the box
g.setColor(Color.BLACK);
g.fillRect(this.x, this.y, 20, 20);
//g.fillRect((+20 to move right one box),(+20 to move down one box), 20, 20);
//g.fillRect((-20 to move left one box),(-20 to move up one box), 20, 20);
}
}
Display.java
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class Display extends JFrame {
int X = 5, Y = 100;
private JButton left, right, up, down;
Graph dude = new Graph(X, Y);
public Display() {
super("nash's graph(moving the box!)");
JButton left = new JButton("move left");
add(left, BorderLayout.WEST);
left.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
X = X - 20;
}
});
JButton right = new JButton("move right");
add(right, BorderLayout.EAST);
right.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
X = X + 20;
}
});
JButton up = new JButton("move up");
add(up, BorderLayout.NORTH);
up.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
Y = Y - 20;
}
});
JButton down = new JButton("move down");
add(down, BorderLayout.SOUTH);
down.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
Y = Y + 20;
}
});
setSize(500, 300);
setVisible(true);
add(dude, BorderLayout.CENTER);
}
}
You need To repaint after you cange the x and y value Like this :
JButton left = new JButton("move left");
add(left, BorderLayout.WEST);
left.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
X = X - 20;
dude.x = X;
dude.y = Y;
repaint();
}
});
JButton right = new JButton("move right");
add(right, BorderLayout.EAST);
right.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
X = X + 20;
dude.x = X;
dude.y = Y;
repaint();
}
});
JButton up = new JButton("move up");
add(up, BorderLayout.NORTH);
up.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
Y = Y - 20;
dude.x = X;
dude.y = Y;
repaint();
}
});
JButton down = new JButton("move down");
add(down, BorderLayout.SOUTH);
down.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
Y = Y + 20;
dude.x = X;
dude.y = Y;
repaint();
}
});
I am learning java. This is my first animation. I want a ball to move up and down continuously when start button is pressed, and it should STOP when stop button is pressed. The code I have written moves the ball 5 times(3 times down and 2 times up). But the panel displays only start and final positions, it does not display intermediate positions. How to display intermediate positions as well?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class dabble
{
private boolean z = true;
private int x=10;
private int y=10;
private JFrame frame;
private JLabel label;
private mypanel panel;
private JButton b1;
private JButton b2;
public static void main (String[] args)
{
dabble dab = new dabble();
dab.start();
}
void start()
{
frame = new JFrame();
label = new JLabel();
panel = new mypanel();
b1= new JButton("Start");
b2= new JButton("Stop");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b1.addActionListener(new al1());
b2.addActionListener(new al2());
frame.getContentPane().add(BorderLayout.NORTH,b1);
frame.getContentPane().add(BorderLayout.SOUTH,b2);
frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.getContentPane().add(BorderLayout.EAST,label);
frame.setSize(600,600);
frame.setVisible(true);
}
void go()
{
for(int i=0;i<5;i++)
{
if(z==false)
break;
//label.setText("Hi");
y=510-y;
panel.repaint();
try{
Thread.sleep(500);
//label.setText("sleep");
}catch(Exception Ex)
{
//label.setText("exp");
}
}
}
class al1 implements ActionListener{
public void actionPerformed(ActionEvent event){
go();
}
}
class al2 implements ActionListener{
public void actionPerformed(ActionEvent event){
z=false;
}
}
class mypanel extends JPanel
{
public void paintComponent ( Graphics g)
{
g.setColor(Color.white);
g.fillRect(0,0,this.getWidth(),this.getHeight());
int red = (int) (Math.random()*255);
int green = (int) (Math.random()*255);
int blue = (int) (Math.random()*255);
Color c1 = new Color(red,green,blue);
g.setColor(c1);
g.fillOval(x,y,20,20);
}
}
}
Calling repaint() does not actually paint the panel - it just marks it to be painted later. And painting always happens on the event dispatch thread, as do event listener notifications.
Since go() is being called on the event dispatch thread (by a button action listener), the panel cannot be repainted while go() is running. You simply queue up a single repaint that happens as soon as go() is done.
What you probably want to do is to use a javax.swing.Timer that fires once every 500 ms, and have its action be to move the ball one step and then call repaint().
Well you perform your loop 5 times (instead of an infinite loop). Moreover you change the vertical position from 10 to 500 and then back to 10 etc... If you want to see intermediate position, you should consider asking to repaint the intermediate positions as well providing the intermediate values of y.
OK, doing the following solves your issues but it is definitely a poor design:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class dabble {
private static final long ANIMATION_DURATION = 5000; // 5 seconds
private static final int REFRESH_RATE = 10;// 10 times per second
private boolean incrementing = true;
private volatile boolean z = true;
private int x = 10;
private volatile int y = 10;
private JFrame frame;
private JLabel label;
private mypanel panel;
private JButton b1;
private JButton b2;
public static void main(String[] args) {
dabble dab = new dabble();
dab.start();
}
void start() {
frame = new JFrame();
label = new JLabel();
panel = new mypanel();
b1 = new JButton("Start");
b2 = new JButton("Stop");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b1.addActionListener(new al1());
b2.addActionListener(new al2());
frame.getContentPane().add(BorderLayout.NORTH, b1);
frame.getContentPane().add(BorderLayout.SOUTH, b2);
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.getContentPane().add(BorderLayout.EAST, label);
frame.setSize(600, 600);
frame.setVisible(true);
}
void go() {
new Animation().start();
}
class al1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
go();
}
}
class al2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
z = false;
}
}
class mypanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color c1 = new Color(red, green, blue);
g.setColor(c1);
g.fillOval(x, y, 20, 20);
}
}
class Animation extends Thread {
private long start;
#Override
public void run() {
start = System.currentTimeMillis();
while (true) {
if (!z) {
return;
}
double progress = (double) (System.currentTimeMillis() - start) / ANIMATION_DURATION;
System.err.println(progress);
if (incrementing) {
y = (int) (10 + 500 * progress);
} else {
y = (int) (510 - 500 * progress);
}
if (progress > 1.0) {
start = System.currentTimeMillis();
incrementing = !incrementing;
}
panel.repaint();
try {
Thread.sleep(1000 / REFRESH_RATE);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}