Hi all,

I'm doing a elevator simulation project but i met some issues.

First, I wish to align my buttons on the left to the horizontal lines. I tried to setting setMinimumSize, setMaximumSize, setPreferredSize but it didn't help.

Second, if I re-size the window, the buttons on the left seems unable to cope with the re-size. Is there anyway to make the button re-size together?

Third, simulation of the elevator works perfectly only when the moving interval, dy0 equals 1. When it's greater than 1, some floor fails.

Fourth, the elevator class background overshot the last horizontal line. I tried setting setSize for elevator class but if I were to resize the window, the background just overshot.

The codes:

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

// The Main class
public class Elevator_Simulation extends JFrame {

    // Declaration of variables
    public JLabel state;        // Display the state of the elevator
    private JLabel id;          // My name and group
    public ButtonPanel control; // Button control panel
    private Elevator elevator;  // Elevator area

    // Constructor
    public Elevator_Simulation() {

        // Create GUI   
        getContentPane().setLayout(new BorderLayout(0, 0));

        // Display title 
        id = new JLabel("Name: Lim Xin Wei    Group: SS2", JLabel.CENTER);
        getContentPane().add(id, BorderLayout.NORTH);

        // Display button panel
        control = new ButtonPanel();
        getContentPane().add(control, BorderLayout.WEST);

        // Display elevator & lines
        elevator = new Elevator(this);
        getContentPane().add(elevator, BorderLayout.CENTER);

        // Display dynamic text
        state = new JLabel("The elevator is moving up", JLabel.CENTER);
        getContentPane().add(state, BorderLayout.SOUTH);
    }

    // Main method
    public static void main(String[] args) {
        // Create a frame and display it
        Elevator_Simulation frame = new Elevator_Simulation();
        frame.setSize(400, 500);
        frame.setLocationRelativeTo(null);
        frame.setTitle("Elevator Simulation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
} // The end of Elevator_Simulation class

// The ButtonPanel class receives and handles button pressing events
class ButtonPanel extends JPanel implements ActionListener {

    // Declaration of variables
    public JButton b[] = new JButton[8];  // 8 Buttons
    public boolean bp[] = new boolean[8]; // State of each button, pressed or not

    // Constructor
    public ButtonPanel() {
        // Create GUI
        setLayout(new GridLayout(8, 1, 0, 0));
        for (int i = 0; i < b.length; i++) {
            b[i] = new JButton("F" + (b.length - i));
            b[i].setBackground(Color.CYAN);
            b[i].addActionListener(this);
            bp[i] = false;
            add(b[i]);
        }
    }

    public void actionPerformed(ActionEvent e) {
        // Handle the button pressing events        
        for (int i = 0; i < b.length; i++) {
            if (e.getSource() == b[i]) {
                b[i].setBackground(Color.RED);
                bp[i] = true;
            }
        }
    }
} // The end of ButtonPanel class

// The elevator class draws the elevator area and simulates elevator movement
class Elevator extends JPanel implements ActionListener {

    // Declaration of variables
    private Elevator_Simulation app;    // Elevator Simulation frame
    private boolean up;                 // Elevator is moving up or down
    private boolean firstRun;           // Elevator initial position flag
    private int width;                  // Elevator's width
    private int height;                 // Elevator's height
    private int xco;                    // X coordinate of the elevator's upper left corner
    private int yco;                    // Y coordinate of the elevator's upper left corner
    private int dy0;                    // Moving interval
    private int topy;                   // Y coordinate of the top level
    private int bottomy;                // Y coordinate of the bottom level
    private Timer tm;                   // Timer to drive the elevator movement
    final int MoveDelay = 40;           // Time between moves 
    final int LoadTime = 99000;          // Time to wait while loading

    // Constructor
    public Elevator(Elevator_Simulation app) {
        // Initialization of variables
        setBackground(Color.YELLOW);
        this.app = app;
        up = true;
        firstRun = true;
        dy0 = 3;
        tm = new Timer(MoveDelay, this);
    }

    // Paint elevator area
    public void paintComponent(Graphics g) {
        // Obtain geometric values of components for drawing the elevator area
        width = app.control.b[0].getWidth();
        height = app.control.b[0].getHeight();
        // Place elevator in middle
        xco = (getWidth() - width) / 2;
        if (firstRun) {
            yco = getHeight() - height;
            firstRun = false;
        }
        topy = 0;
        // Resize the window will make bottomy value inaccruate
        bottomy = this.getHeight() - height;

        // Clear the painting canvas
        super.paintComponent(g);

        // Start the Timer if not started elsewhere
        if (!tm.isRunning()) {
            tm = new Timer(MoveDelay, this);
            tm.setInitialDelay(1000);
            tm.start();
        }

        // Draw horizontal lines 
        for (int i = 0; i <= 9; i++) {
            g.setColor(Color.GRAY);
            g.drawLine(0, height * i, getWidth(), height * i);
        }

        // Draw elevator
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(xco, yco, width, height);

        // Draw vertical line striking through elevator
        g.setColor(Color.DARK_GRAY);
        g.drawLine(xco + (width / 2), yco, xco + (width / 2), (yco + height));
    }

    // Handle the timer events
    public void actionPerformed(ActionEvent e) {

        int current = (yco / height);

        
        if (up) {
            app.state.setText("The elevator is moving up");
            yco -= dy0;

            if (app.control.bp[current]) {
                if ((yco + height) >= (height * current) && (yco + height) <= (height * (current + 1))) {
                    tm.stop();
                    app.control.bp[current] = false;
                    app.control.b[current].setBackground(Color.CYAN);
                    app.state.setText("The elevator is picking up passengers at floor " + (8 - current));
                }
            }

            if (yco <= topy) {
                up = false;
            }

        } else {
            app.state.setText("The elevator is moving down");
            yco += dy0;

            if (app.control.bp[current]) {
                if ((yco) >= (height * current) && (yco) <= (height * (current + 1))) {
                    tm.stop();
                    app.control.bp[current] = false;
                    app.control.b[current].setBackground(Color.CYAN);
                    app.state.setText("The elevator is picking up passengers at floor " + (8 - current));
                }
            }

            if (yco >= bottomy) {
                up = true;
            }
        }

        // Repaint the panel
        repaint();
    }
} // The end of Elevator class

Guidance required ! Thanks in advanced

I did not have a problem with the first two issues.
Can you be more specific about the other two issues?
The value of dy0 is 3 in the posted code. What is different about how the posted code runs when you change dy0 to 1?

You need to try debugging the code by adding printlns to show the values of the controlling variables so you can see where your logic is wrong. If the y value for where the elevator stops doesn't align with the y value of the top of the elevator, you need to print out there values to see what the problem is.

Sorry, I think I fail to give a proper thought to my questions that I'm asking.

For the 1st and 2nd issue, the first button "F8" is slightly off align with the first line. If you re-size the window, it is possible to make the button align with the first line. I do not know if its my laptop issue, i do know that some people doesn't have my alignment issue.

Ignore the 3rd issue.

4th issue, my idea was that the lines are being drawn according to the height of the button on the left, thus the last line should be at the end of the panel. But when i setBackground(Color.YELLOW), it is obvious that the yellow overshot the last line. When you re-size the window, the yellow background just overshot even more.

5th issue, the vertical line draw at the middle of the elevator overshot the elevator area. I had to add "+ 1" at line 146 g.drawLine(xco + (width / 2), yco, xco + (width / 2), (yco + height) + 1) to remove the overshot. Can explain to me why is it so ?

6th issue, when the elevator is coming down example, from level 4 to level 3, when the elevator if halfway between level 4 n level 3, press the "F4" button, and the elevator stops.

My suggestion is to add printlns to display the values of the variables as they change to see why your logic is not working the way you want.

For the yellow to not extend past the bottom of the buttons on the left, try changing the layout manager so the buttons are in the same container with the yellow object so their bottoms are on the same horizontal line.

How about the alignment issue ? yours fit in perfectly ? is there any explanations to the off alignment I'm facing ?

The alignment issue i facing :

If i change the layout for the button , how do i make the button vertically place? actually i'm only allow to use what's has been taught to us, which is grid, flow, border. Grid layout is the best way to do it. is there other alternatives ?

just as @NormR1 suggested debug alighment to the FloorsLines by using System.out.println(someValue);

1/ still you have problem with TOP & BOTTOM, where elevator JUMP-OUT (2-3 pixels)
2/ same for each FLOOR

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

// The Main class, The ButtonPanel class receives and handles button pressing events
public class Elevator_Simulation extends JFrame {

    private static final long serialVersionUID = 1L;// Declaration of variables    
    public JLabel state;        // Display the state of the elevator
    private JLabel id;          // My name and group
    public ButtonPanel control; // Button control panel
    private Elevator elevator;  // Elevator area
    private JFrame frame = new JFrame();

    public Elevator_Simulation() {// Constructor
        id = new JLabel("Name: Lim Xin Wei    Group: SS2", JLabel.CENTER); // Display title 
        control = new ButtonPanel(); // Display button panel
        elevator = new Elevator(this);// Display elevator & lines
        state = new JLabel("The elevator is moving up", JLabel.CENTER);// Display dynamic text
        frame.setLayout(new BorderLayout(0, 0)); // Create GUI  
        frame.add(id, BorderLayout.NORTH);
        frame.add(control, BorderLayout.WEST);
        frame.add(elevator, BorderLayout.CENTER);
        frame.add(state, BorderLayout.SOUTH);
        frame.setLocationRelativeTo(null);
        frame.setPreferredSize(new Dimension(400, 500));
        frame.setTitle("Elevator Simulation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {// Main method
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Elevator_Simulation frame = new Elevator_Simulation();// Create a frame and display it
            }
        });
    }
} // The end of Elevator_Simulation class

class ButtonPanel extends JPanel implements ActionListener {

    private static final long serialVersionUID = 1L;// Declaration of variables
    public JButton b[] = new JButton[8];  // 8 Buttons
    public boolean bp[] = new boolean[8]; // State of each button, pressed or not

    ButtonPanel() {// Constructor

        setLayout(new GridLayout(8, 1)); // Create GUI
        for (int i = 0; i < b.length; i++) {
            b[i] = new JButton("F" + (b.length - i));
            b[i].setBackground(Color.CYAN);
            b[i].addActionListener(this);
            bp[i] = false;
            add(b[i]);
        }
    }

    public void actionPerformed(ActionEvent e) {
        for (int i = 0; i < b.length; i++) { // Handle the button pressing events        
            if (e.getSource() == b[i]) {
                b[i].setBackground(Color.RED);
                bp[i] = true;
            }
        }
    }
} // The end of ButtonPanel class

class Elevator extends JPanel implements ActionListener {// The elevator class draws the elevator area and simulates elevator movement

    private static final long serialVersionUID = 1L; // Declaration of variables
    private Elevator_Simulation app;    // Elevator Simulation frame
    private boolean up;                 // Elevator is moving up or down
    private boolean firstRun;           // Elevator initial position flag
    private int width;                  // Elevator's width
    private int height;                 // Elevator's height
    private int xco;                    // X coordinate of the elevator's upper left corner
    private int yco;                    // Y coordinate of the elevator's upper left corner
    private int dy0;                    // Moving interval
    private int topy;                   // Y coordinate of the top level
    private int bottomy;                // Y coordinate of the bottom level
    private Timer tm;                   // Timer to drive the elevator movement
    final int MoveDelay = 40;           // Time between moves 
    final int LoadTime = 99000;          // Time to wait while loading

    Elevator(Elevator_Simulation app) { // Constructor       
        setBackground(Color.YELLOW); // Initialization of variables
        this.app = app;
        up = true;
        firstRun = true;
        dy0 = 3;
        tm = new Timer(MoveDelay, this);
    }

    @Override
    public void paintComponent(Graphics g) { // Paint elevator area    
        width = app.control.b[0].getWidth(); // Obtain geometric values of components for drawing the elevator area
        height = app.control.b[0].getHeight();

        xco = (getWidth() - width) / 2; // Place elevator in middle
        if (firstRun) {
            yco = getHeight() - height;
            firstRun = false;
        }
        topy = 0;
        bottomy = this.getHeight() - height; // Resize the window will make bottomy value inaccruate
        super.paintComponent(g); // Clear the painting canvas
        if (!tm.isRunning()) { // Start the Timer if not started elsewhere
            tm = new Timer(MoveDelay, this);
            tm.setInitialDelay(1000);
            tm.start();
        }
        for (int i = 0; i <= 9; i++) { // Draw horizontal lines 
            g.setColor(Color.GRAY);
            g.drawLine(0, height * i, getWidth(), height * i);
        }
        g.setColor(Color.LIGHT_GRAY);// Draw elevator
        g.fillRect(xco, yco, width, height);
        g.setColor(Color.DARK_GRAY); // Draw vertical line striking through elevator
        g.drawLine(xco + (width / 2), yco, xco + (width / 2), (yco + height));
    }

    public void actionPerformed(ActionEvent e) {// Handle the timer events
        int current = (yco / height);
        if (up) {
            app.state.setText("The elevator is moving up");
            yco -= dy0;
            if (app.control.bp[current]) {
                if ((yco + height) >= (height * current) && (yco + height) <= (height * (current + 1))) {
                    tm.stop();
                    app.control.bp[current] = false;
                    app.control.b[current].setBackground(Color.CYAN);
                    app.state.setText("The elevator is picking up passengers at floor " + (8 - current));
                }
            }
            if (yco <= topy) {
                up = false;
            }
        } else {
            app.state.setText("The elevator is moving down");
            yco += dy0;
            if (app.control.bp[current]) {
                if ((yco) >= (height * current) && (yco) <= (height * (current + 1))) {
                    tm.stop();
                    app.control.bp[current] = false;
                    app.control.b[current].setBackground(Color.CYAN);
                    app.state.setText("The elevator is picking up passengers at floor " + (8 - current));
                }
            }
            if (yco >= bottomy) {
                up = true;
            }
        }
        repaint(); // Repaint the panel
    }
} // The end of Elevator class

To get data on the problem, print out the bounds of the elevator, control and the bottom button. The size of the elevator is not an even multiple of the size of a button.

Have you tried making the floors with the elevator separate components that correspond to the buttons instead of having it be one large component that you draw lines on?
The trick would be drawing the elevator over the top of the floors as it went from floor to floor. Don't know how to do that.

1st and 2nd issue has been resolved. I believe I fail to install my IDE correctly which cause this issue, I went to re-install and the alignment now went back to normal.

4th, I remove setBackground instead I use fillRect to draw my background and set to yellow. Now my last line and background is tie together, just that the buttons panel is 1 pixel shorter than my elevator panel.

I'm still working on the 5th and 6th issue.
I did printout the bounds of the components. the height is 53 and width is 47.
But i don't get it why the vertical line is 1 pixel longer than the elevator itself.
As for the algorithm for the elevator simulation, I still have no clue on solving the halfway stopping

JComponets inside JPanel has diferrent Size as JPanel nested this JComponet(s)

i don't get what you meant.

the vertical line and elevator rectangle is drawn based on the size of the button, but now the vertical line is 1 pixel longer than the elevator rectangle.

unless there are codes disturbing the size, i don't see why the vertical line is not on par with the height of the elevator rectangle.

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.