Question

I am writing the implementation of Galton Board in Java by using Java awt, Swing and thread. My Program has three text field to choose number of slots, number of balls, and number of ball drops at the same time, two buttons one for display and one for start the program. I try to make it work like I can choose the amount of balls and click start and the balls auto falling down the chimney. My program currently can drop any balls, but they are falling at the same time, any ideas to make the ball falling follow each other?. Any suggestions or help are appreciated, Thank you.

This is Main.Class

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Random;
import javax.swing.*;

public class Main extends JFrame {
    private String num_slots;
    private String num_balls;
    private String ball_free;
    private JButton Display;
    private JButton Start;
    private JPanel textpanel;
    private JPanel mainpanel;
    private JPanel graphpanel;

    public Main() {
        textpanel = new JPanel();
        textpanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 20));
        textpanel.add(new JLabel("Number of Slots"));
        final JTextField text1 = new JTextField(10);
        textpanel.add(text1);
        textpanel.add(new JLabel("Number of Balls"));
        final JTextField text2 = new JTextField(10);
        textpanel.add(text2);
        textpanel.add(new JLabel("How many balls can be freed"));
        final JTextField text3 = new JTextField(10);
        textpanel.add(text3);
        Display = new JButton("Display");
        textpanel.add(Display);
        Start = new JButton("Start");
        textpanel.add(Start);
        // Create panel p2 to hold a text field and p1
        mainpanel = new JPanel(new BorderLayout());
        mainpanel.add(textpanel, BorderLayout.NORTH);
          /*
           * graphpanel = new JPanel(); graphpanel.setLayout(new
           * BoxLayout(graphpanel, BoxLayout.Y_AXIS));
           */
        add(mainpanel, BorderLayout.CENTER);
        Display.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == Display) {
                    num_slots = text1.getText();
                    int slots = Integer.parseInt(num_slots);
                    num_balls = text2.getText();
                    int balls = Integer.parseInt(num_balls);
                    MainPanel pa = new MainPanel(slots, balls);
                    mainpanel.add(pa);
                    mainpanel.revalidate();
                }
            }
        });
        Start.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == Start) {
                    num_slots = text1.getText();
                    int slots = Integer.parseInt(num_slots);
                    num_balls = text2.getText();
                    int balls = Integer.parseInt(num_balls);
                    MainPanel pa = new MainPanel(slots, balls);
                    mainpanel.add(pa, BorderLayout.CENTER);
                    pa.start();
                    mainpanel.revalidate();
                    mainpanel.repaint();
                }
            }
        });
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Main frame = new Main();
        frame.setTitle("The Galton board");
        frame.setSize(1000, 800);
        frame.setLocationRelativeTo(null); // Center the frame
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setAutoRequestFocus(true);
    }
}

main panel class contains the chimneys and balls

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JPanel;

class MainPanel extends JPanel implements Runnable {
    private int num;
    private int number_ball;
    public static int start_y = 100;
    private float ball_x = 385;
    private float ball_y = 50;
    private float radius = 15;
    private static int panel_x = 300;
    private static int panel_y = 100;
    private int diameter = 20;
    private int last_x = 0;
    private final static Random generator = new Random();
    ArrayList<Balls> list_ball = new ArrayList<Balls>();
    private int m_interval = 100;
    private Timer m_timer;

    public MainPanel() {
    }

    public MainPanel(int number) {
        num = number;
    }

    public MainPanel(int number, int ball) {
        num = number;
        number_ball = ball;
        for (int i = 1; i <= number_ball; i++) {
            list_ball.add(new Balls());

        }
        m_timer = new Timer(m_interval, new TimerAction());
    }

    public int getPanel_y() {
        return panel_y;
    }

    public void start() {
        m_timer.setInitialDelay(250);
        m_timer.start();

    }

    @Override
    protected void paintComponent(Graphics g) {
        int start_y = 100;
        panel_x = 300;
        panel_y = 100;
        diameter = 20;
        last_x = 0;
        super.paintComponent(g);
        if (num % 2 == 0) {
            for (int i = 1; i <= num; i++) {
                if ((i % 2) != 0) {
                    for (int k = 1; k <= num; k++) {
                        g.setColor(Color.BLUE);
                        g.fillOval(panel_x, panel_y, diameter, diameter);
                        panel_x = panel_x + 40;
                    }
                } else if ((i % 2) == 0) {
                    for (int k = 1; k <= num + 1; k++) {
                        g.setColor(Color.BLUE);
                        g.fillOval(panel_x - 20, panel_y, diameter, diameter);
                        panel_x = panel_x + 40;
                    }
                }
                panel_y = panel_y + 40;
                panel_x = 300;
            }
        } else if (num % 2 != 0) {
            for (int i = 1; i <= num; i++) {
                if ((i % 2) != 0) {
                    for (int k = 1; k <= num; k++) {
                        g.setColor(Color.BLUE);
                        g.fillOval(panel_x, panel_y, diameter, diameter);
                        panel_x = panel_x + 40;
                    }
                } else if ((i % 2) == 0) {
                    for (int k = 1; k <= num + 1; k++) {
                        g.setColor(Color.BLUE);
                        g.fillOval(panel_x - 20, panel_y, diameter, diameter);
                        panel_x = panel_x + 40;
                    }
                }
                panel_y = panel_y + 40;
                panel_x = 300;
            }
        }
        for (int n = 40; n < panel_y - 40; n = n + 40) {
            if (num % 2 == 0) {
                g.drawLine(panel_x - 50 + n, panel_y - 10, panel_x - 50 + n,
                        panel_y + 80);
                g.drawLine(panel_x, panel_y + 80, panel_x - 50 + n, panel_y + 80);
                last_x = panel_x - 50 + n;
            } else if (num % 2 != 0) {
                g.drawLine(panel_x - 30 + n, panel_y - 10, panel_x - 30 + n,
                        panel_y + 80);
                g.drawLine(panel_x, panel_y + 80, panel_x - 30 + n, panel_y + 80);
                last_x = panel_x - 30 + n;
            }
        }
        for (int i = 0; i < list_ball.size(); i++) {
            list_ball.get(i).draw(g);

        }
    }

    class TimerAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            for (int i = 0; i < list_ball.size(); i++) {

                list_ball.get(i).move();
                //return;

                //m_timer.stop();
                repaint();


            }
        }

Balls Class

import java.awt.geom.Ellipse2D;
import java.util.Random;
import java.awt.*;

public class Balls {
    private Ellipse2D.Double thisBall;
    private int Ball_x;
    private int Ball_y;
    public int radius;
    public  int start_y;
    private final static Random generator = new Random();
    Mainpanel pa = new Mainpanel();
    public Balls()
    {
        start_y = 100;
        Ball_x = 385;
        Ball_y = 50;
        radius = 15;

    }
    public void draw(Graphics g)
    {
        g.setColor(Color.RED);
        g.fillOval(Ball_x, Ball_y, radius, radius);
    }
    public void move()
    {
        if (Ball_y < pa.getPanel_y() + 65)
        {
            int direction = generator.nextInt(2);
            Ball_y = Ball_y + 5;
            if (Ball_y == start_y - 10 && start_y < pa.getPanel_y())
            {
                if (direction == 0)
                {
                    Ball_x = Ball_x - 20;
                }
                else Ball_x = Ball_x + 20;
                start_y = start_y + 40;
            }

            System.out.println(Ball_y);
            System.out.println(pa.getPanel_y());
        }
        // Ball_x = Ball_x + 5;


    }
}
Was it helpful?

Solution

"My program currently can drop any balls, but they are falling at the same time, any ideas to make the ball falling follow each other?"

One Option..

As seen in this answer, add a delayed state to each Ball. For example (from the same answer)

class Shape {

    int randXLoc;
    int y = D_HEIGHT;
    int randomDelayedStart;
    boolean draw = false;
    boolean down = false;
    Color color;

    public Shape(int randXLoc, int randomDelayedStart, Color color) {
        this.randXLoc = randXLoc;
        this.randomDelayedStart = randomDelayedStart;
        this.color = color;
    }

    public void drawShape(Graphics g) {
        if (draw) {
            g.setColor(color);
            g.fillOval(randXLoc, y, 30, 30);
        }
    }

    public void decreaseDelay() {
        if (randomDelayedStart <= 0) {
            draw = true;
        } else {
            randomDelayedStart -= 1;
        }
    }
}

As you can see, the Shape is constructed with a randomDelayedStart. With every tick of the Timer, the randomDelayedStart is decreased until it reaches zero. In which case, the flag to draw is raised, allowing for the drawShape() to take effect. There is also a move() method (not shown for brevity) that uses the same flag, so the shape move() has no affect until the flag is raised

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top