2

When I try to add a second instance of an elevator class, the first one disappears. How can I rearrange this code in order to see both objects?

Here is my main class:

public class MainClass extends JPanel implements ActionListener {
    public static void main(String[] args) {
        JFrame frame = new JFrame("title");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1000, 700);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        Component component1 = frame.add(new elevator(0,0));
        Component component2 = frame.add(new elevator(505,50));   
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
    }
}

And this is the elevator class:

public class elevator extends JPanel implements ActionListener {
    Timer timer;
    private double angle = 0;
    private double scale = 1;
    private double delta = 0.01;
    private int x=0;
    private int y=0;

    Rectangle.Float r = new Rectangle.Float(0, 0, 3, 3);

    public elevator(int input_x, int input_y) {
        x=input_x;
        y=input_y;
        timer = new Timer(10, this);
        timer.start();
    }

    public elevator() {
        timer = new Timer(10, this);
        timer.start();
    }

    public void paint(Graphics g) {
        this.setSize(100,200);
        this.setLocation(x, y);
        int h = getHeight();
        int w = getWidth();

        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g2d.translate(w / 5, scale*140);
        g2d.scale(20, 20);

        g2d.fill(r);
    }

    public void actionPerformed(ActionEvent e) {
        if (scale < 0.01 || scale > 0.99) {
            delta = -delta;
        } 
        scale += delta;
        angle += 0.01;
        repaint();
    }
}
2
  • Learn about layout managers. The default layout of a JFrame is a BorderLayout. Commented May 23, 2014 at 13:36
  • Also, components should be added to the frame before the frame is made visible. Commented May 23, 2014 at 15:08

4 Answers 4

2

You will need some sort of container to put both of the components in. You could use a JPanel, in which case your code would look like:

JPanel panel = new JPanel();
panel.add(new elevator(0,0));
panel.add(new elevator(505,50));
frame.add(panel);

For both of them to take up the same area (and for the JPanel to fill up all the space it can), you could pass in a GridLayout to the JPanel constructor:

JPanel panel = new JPanel(new GridLayout(2, 1)); // 2 rows, 1 column

or

JPanel panel = new JPanel(new GridLayout(1, 2)); // 1 row, 2 columns
Sign up to request clarification or add additional context in comments.

Comments

2

Don't make elevator extends JPanel at all. Just make it a class for holding state, manipulating the state, and drawing the state. Then just have one main drawing panel, that you add elevators to, using a List<elevator>.

Elevator.java (notice Java naming convention)

public class Elevator {
    public void draw(Graphics g) {}
    public void move() {}
}

ElevatorPanel.java

public class ElevatorPanel extends JPanel {
    List<Elevator> elevators;

    @Override
    protected void paintComponent(Grapchics g) {
        super.paintComponent(g);
        for (Elevator elevator: elevators) {
            elevator.draw(g);
        }
    }
}

Just have the timer (only one) in the ElevatorPanel class and loop through the list of elevators and call the move method.

Timer timer = new Timer(40, new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        for (Elevator elevator : elevators) {
            elevator.move();
        }
        repaint();
    }
});

You can see a bunch of similar examples here and here and here and here and here and here.


Side Notes:

  • Follow Java naming convention. Class names begin with upper case letters.

  • You should be override paintComponent and not paint

  • Swing apps should be run on the Event Dispatch Thread. See Initial Threads

Comments

1

A frame can only handle one component by default. Create a JPanel and add it to the JFrame, then specify a layout for your JPanel and start adding components to it, instead of the frame

Comments

0

UPDATED

Strictly speaking, all I think you need to do to get the code working may be this. Specify a BorderLayout position when you add to the frame:

frame.add(new elevator(0, 0), BorderLayout.WEST);
frame.add(new elevator(505, 50), BorderLayout.EAST);

The other answers here are of course proposing better long term approaches to your project code.

(Thanks sbat for pointing out that the default layout is actually BorderLayout not FlowLayout).

Cheers,

2 Comments

frame.add(...) will do the same thing as frame.getContentPane().add(...) nowadays. The default layout for a JFrame is BorderLayout, not FlowLayout. BorderLayout will add components to the center if you don't specify otherwise, and it'll replace the last component that was in the center, which is what the OP is experiencing. If the OP chooses to go with a FlowLayout, then they'll also need to specify a preferred size for each of the components.
Thanks sbat, your advice led to identifying the root cause of the display error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.