3

I'm creating a bridge crossing game for my computer science class and we need to create a graphical representation of the problem. The graphical representation is drawn by the BridgeCanvas class. This class extends the Canvas class which extends from JComponent.

I know the BridgeCanvas is correctly drawing the graphic because when I add a BridgeCanvas object directly to a JFrame it displays correctly, but when I put the BridgeCanvas into a JPanel first and then add that to the JFrame, it doesn't show up (all I get is a blank frame). One of my classmates said it might be because I'm using a Mac. Also I'm doing this in netbeans.

Here is the BridgeCanvas class (the main method is contained in this class as well) :

public class BridgeCanvas extends Canvas {

// Initializes the background, river, bridge, and character graphics    
public BridgeCanvas(State state) {
    super(state);

    background = new RoundRectangle2D.Double(0, 0, 400, 400, 40, 40);

    bridge = new GeneralPath();
    bridge.moveTo(100, 175);
    bridge.curveTo(200, 120, 200, 120, 300, 175);
    bridge.lineTo(300, 225);
    bridge.curveTo(200, 170, 200, 170, 100, 225);
    bridge.closePath();

    river = new GeneralPath();
    river.moveTo(150, 0);
    river.curveTo(50, 100, 150, 200, 150, 200);
    river.curveTo(225, 300, 150, 400, 150, 400);
    river.lineTo(250, 400);
    river.curveTo(325, 300, 250, 200, 250, 200);
    river.curveTo(150, 100, 250, 0, 250, 0);
    river.closePath();

    AffineTransform transform = new AffineTransform();
    transform.setToTranslation(25, 25);

    // generateShapeFromText is method used to create shapes from numbers.

    P1 = (GeneralPath) generateShapeFromText(new Font(Font.MONOSPACED, Font.BOLD, 32), "P1");
    P1 = (GeneralPath) P1.createTransformedShape(transform);
    P2 = (GeneralPath) generateShapeFromText(new Font(Font.MONOSPACED, Font.BOLD, 32), "P2");
    transform.setToTranslation(25, 100);
    P2 = (GeneralPath) P2.createTransformedShape(transform);
    FL = (GeneralPath) generateShapeFromText(new Font(Font.MONOSPACED, Font.BOLD, 32), "F");
    P5 = (GeneralPath) generateShapeFromText(new Font(Font.MONOSPACED, Font.BOLD, 32), "P5");
    P10 = (GeneralPath) generateShapeFromText(new Font(Font.SANS_SERIF, Font.BOLD, 32), "P10");


}

public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    super.paintComponent(g); 
    g2.setFont(new Font(Font.MONOSPACED, Font.BOLD, 32));
    BridgeState state = (BridgeState) getState();

    g2.setColor(new Color(0, 140, 0));
    g2.fill(background);
    g2.setColor(new Color(0, 0, 200));
    g2.fill(river);
    g2.setColor(new Color(169, 69, 19));
    g2.fill(bridge);
    g2.setColor(Color.BLACK);
    g2.fill(P1);
    g2.fill(P2);

}


private RoundRectangle2D.Double background;
private GeneralPath bridge;
private GeneralPath river;
private GeneralPath P1;
private GeneralPath P2;
private GeneralPath FL;
private GeneralPath P5;
private GeneralPath P10;

public static void main(String[] args) {
    JFrame frame = new JFrame();
    BridgeState state = new BridgeState(Position.WEST, Position.WEST, Position.WEST, Position.WEST, Position.WEST, 0);
    BridgeCanvas canvas = new BridgeCanvas(state);
    JComponent panel = new JPanel();
    panel.add(canvas);
    panel.setLayout(new FlowLayout());
    panel.setOpaque(false);
    panel.setSize(new Dimension(440, 440));

    frame.setPreferredSize(new Dimension(440, 440));
    frame.add(panel);

    frame.setVisible(true);
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

}

1 Answers1

3

Look at the size of your BridgeCanvas object. If you add it to the JPanel and the JPanel uses its default FlowLayout, then the JComponent derived object will be at most 1 by 1 pixel in size and thus while it has been created, added and displayed, nothing worthwhile will be visible.

In fact this can easily be tested by (temporarily) tucking a getSize() method in your BridgeCanvas's paintComponent(...) method, a method which will only be called if the object is displayed:

public void paintComponent(Graphics g) {

    // TODO: delete line below!
    System.out.println("BridgeCanvas Size: " + getSize());

    Graphics2D g2 = (Graphics2D) g;
    super.paintComponent(g); 
    g2.setFont(new Font(Font.MONOSPACED, Font.BOLD, 32));

    // .... etc...

}

A possible solution: override BridgeCanvas's getPreferredSize() method, and have it return a Dimension that holds the size you wish it to actually be.

Note: you'll want to avoid calling setSize() on anything, and you'll also want to avoid (per notes Swing expert Jeanette/kleopatra) calling setPreferredSize() since this setting can be changed by the code that uses your BridgeCanvas object.

Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373