0

I am trying to add multiple instances of a class to a JFrame in java, but when I try to add two different instances to the JFrame, only the most recently added is displayed.

I have looked at the answers shown here: How to add multiple components to a JFrame? and here:Adding multiple classes to a Jframe

My code is modeled after https://www.youtube.com/watch?v=I3usNR8JrEE&index=51&list=PL53A7C2BE1F8D780C and I am using Eclipse Java Oxygen release 4.7.1a but nothing has worked for me. Here is my main function:

package BlockPack;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Block extends JPanel implements ActionListener {

    @Override public Dimension getPreferredSize() { 
        return new Dimension(900, 900);
    }

    Timer tm = new Timer(50, this);
    int blockWidth, blockHeight;
    int x, y, velX = 2, velY = 0, gravity = 0;
    String thisName;
    boolean collidingGround = false;

    public Block(String _name, int _x, int _y, int _width, int _height) {
        thisName = _name;
        x = _x;
        y = _y;
        blockWidth = _width;
        blockHeight = _height;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.fillRect(x, y, blockWidth, blockHeight);

        tm.start();
    }

    public void actionPerformed(ActionEvent e) {
        performMovement();
        repaint();
    }

    private void performMovement() {

        y += 1;

    }

    public static void main(String[] args) {
        Block b = new Block("block1", 10, 30, 50, 50);
        Block bb = new Block("block2", 30, 60, 10, 60);

        JFrame jf = new JFrame();

        jf.setLayout(new FlowLayout());

        jf.setTitle("Ball");
        jf.setSize(600, 400);

        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container c = jf.getContentPane();
        c.add(new Block("block1", 10, 30, 50, 50));
        c.add(new Block("block2", 30, 60, 10, 60));

        jf.setVisible(true);
    }

}
Ninjakid14
  • 31
  • 9
  • see https://stackoverflow.com/questions/10086936/java-adding-components-to-jframe – IEE1394 Dec 12 '17 at 20:47
  • Post a complete minimal example reproducing the problem. It works fine here, although you should make the frame visible **after** you've added the blocks, and respect Swing's threading rules. Here's my complete minimal example: https://gist.github.com/jnizet/3910ae413d22ca7f153d9fdc41e22086 – JB Nizet Dec 12 '17 at 20:50
  • @IEE1394 Thank you for the recommendation, but that has yielded the same result as before. Only the last one added is displayed – Ninjakid14 Dec 12 '17 at 20:51
  • My recommendation is to post a complete minimal example reproducing the problem. You haven't done that yet. And as you see, a reasonable guess of what your actual code does doesn't allow us to reproduce the problem. So, without a complete example, we can't help. – JB Nizet Dec 12 '17 at 20:55
  • work on the content pane of your JFrame instead of the JFrame itself Container c = myFrame.getContentPane(); c.add(new JButton("OK")); – IEE1394 Dec 12 '17 at 21:00
  • @IEE1394 quote from the javadoc of JFrame: *As a convenience, the add, remove, and setLayout methods of this class are overridden, so that they delegate calls to the corresponding methods of the ContentPane*. So no, that won't change anything. – JB Nizet Dec 12 '17 at 21:08
  • @IEE1394 yes agreeing with JB Nizet I have tried to replace jf.add() with defining the container as c then calling c.add() with the same argument but that still only displays the previous one added. I also tried creating two different containers and adding one Block() to each, but the same result – Ninjakid14 Dec 12 '17 at 21:16

1 Answers1

0
  1. jf.setLayout(new FlowLayout()); is commented out, so you're adding both components to the center location of the default BorderLayout, and thus of course only the last one is being displayed.
  2. Your Block doesn't override getPreferredSize(), so the default value (10 x 10) is returned, and the component draws outside of this preferred size.
  3. You're not respecting Swing threading rules, and you add your component after the frame is made visible, instead of adding them before it's made visible.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks! so, if i do not comment out that setLayout line, then nothing is displayed, so i figured it was not relevant. also how could I change my code to override getPreferredSize() – Ninjakid14 Dec 12 '17 at 21:37
  • Well, you override it. For example: `@Override public Dimension getPreferredSize() { return new Dimension(200, 200); }` – JB Nizet Dec 12 '17 at 22:16
  • Sorry for the extreme inexperience, i'm brand new to Java. Am I supposed to put the override Dimension at the top of my Block class? I suppose I don't understand how that is supposed to make both of the Block() objects be displayed. I mean does that automatically execute, or do i have to call it somewhere? – Ninjakid14 Dec 12 '17 at 22:26
  • Many layout managers call getPreferredSize() on the component to know how much space they must use in the container to display the component. If you just add other components to a JPanel, the preferred size of the JPanel is computed by combining the preferred size of all the components. But if you don't add any component (as you're doing), then the preferred size can't be known. So it's up to you to override the method and decide what to return. – JB Nizet Dec 12 '17 at 22:32
  • wheer should the `@Override public Dimension getPreferredSize() { return new Dimension(200, 200); }` be placed in my code? – Ninjakid14 Dec 12 '17 at 22:44
  • You have a single class. Where could it be other than in that class. You want BlockPack to have a preferred size. – JB Nizet Dec 12 '17 at 23:19
  • I have tried everything posted so far, but still only one shape is being drawn. – Ninjakid14 Dec 12 '17 at 23:57
  • Edit your question, and show how you applied the 3 fixes in my answer. – JB Nizet Dec 13 '17 at 00:00
  • In its current state, it does not display anything – Ninjakid14 Dec 13 '17 at 00:07
  • Because you want to display 2 blocks, 900 pixels-large (so, 1800 pixels in toatl), in a frame that you set 600 pixels large. That can't possibly fit. Set the preferred size to 200*200 for example, as I posted in my previous comment, and you'll see your two blocks. And fix the threading issue, as I posted in my very first comment on your question. – JB Nizet Dec 13 '17 at 00:11