3

我正在为我的计算机科学课创建一个过桥游戏,我们需要创建问题的图形表示。图形表示由 BridgeCanvas 类绘制。该类扩展了从 JComponent 扩展而来的 Canvas 类。

我知道 BridgeCanvas 正在正确绘制图形,因为当我将 BridgeCanvas 对象直接添加到 JFrame 时,它​​会正确显示,但是当我先将 BridgeCanvas 放入 JPanel 然后将其添加到 JFrame 时,它​​不会显示(全部我得到的是一个空白帧)。我的一位同学说这可能是因为我使用的是 Mac。我也在netbeans中这样做。

这是 BridgeCanvas 类(主要方法也包含在该类中):

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);
}

}
4

1 回答 1

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.

于 2013-03-31T00:46:21.340 回答