2009-06-10 32 views
2

下面的代码是从书籍对象第一次用Java通过Michale Kolling和David J Barnes,以下是本书的练习(ex 5.49)。例如:改进你的drawFrame方法以自动适应当前画布的大小。为此,您需要了解如何使用Dimension类的对象。如何让Jpanel扩展到JFrame的大小?

在下文类BallDemo有一个叫做创建方法的drameFrame.The意图方法是绘制窗口内的矩形20像素和重新绘制矩形时帧的尺寸被改变

import java.awt.*; 
import java.awt.geom.*; 

/** 
* Class BallDemo - provides two short demonstrations showing how to use the 
* Canvas class. 
* 
* @author Michael Kolling and David J. Barnes 
* @version 2008.03.30 
*/ 

public class BallDemo 
{ 
    private Canvas myCanvas; 

    /** 
    * Create a BallDemo object. Creates a fresh canvas and makes it visible. 
    */ 
    public BallDemo() 
    { 
     myCanvas = new Canvas("Ball Demo", 600, 500); 
     myCanvas.setVisible(true); 
    } 

    /** 
    * Demonstrate some of the drawing operations that are 
    * available on a Canvas object. 
    */ 
    public void drawDemo() 
    { 
     myCanvas.setFont(new Font("helvetica", Font.BOLD, 14)); 
     myCanvas.setForegroundColor(Color.red); 

     myCanvas.drawString("We can draw text, ...", 20, 30); 
     myCanvas.wait(1000); 

     myCanvas.setForegroundColor(Color.black); 
     myCanvas.drawString("...draw lines...", 60, 60); 
     myCanvas.wait(500); 
     myCanvas.setForegroundColor(Color.gray); 
     myCanvas.drawLine(200, 20, 300, 50); 
     myCanvas.wait(500); 
     myCanvas.setForegroundColor(Color.blue); 
     myCanvas.drawLine(220, 100, 370, 40); 
     myCanvas.wait(500); 
     myCanvas.setForegroundColor(Color.green); 
     myCanvas.drawLine(290, 10, 320, 120); 
     myCanvas.wait(1000); 

     myCanvas.setForegroundColor(Color.gray); 
     myCanvas.drawString("...and shapes!", 110, 90); 

     myCanvas.setForegroundColor(Color.red); 

     // the shape to draw and move 
     int xPos = 10; 
     Rectangle rect = new Rectangle(xPos, 150, 30, 20); 

     // move the rectangle across the screen 
     for(int i = 0; i < 200; i ++) { 
      myCanvas.fill(rect); 
      myCanvas.wait(10); 
      myCanvas.erase(rect); 
      xPos++; 
      rect.setLocation(xPos, 150); 
     } 
     // at the end of the move, draw once more so that it remains visible 
     myCanvas.fill(rect); 
    } 

    /** 
    * Simulate two bouncing balls 
    */ 
    public void bounce() 
    { 
     int ground = 400; // position of the ground line 

     myCanvas.setVisible(true); 

     // draw the ground 
     myCanvas.drawLine(50, ground, 550, ground); 

     // crate and show the balls 
     BouncingBall ball = new BouncingBall(50, 50, 16, Color.blue, ground, myCanvas); 
     ball.draw(); 
     BouncingBall ball2 = new BouncingBall(70, 80, 20, Color.red, ground, myCanvas); 
     ball2.draw(); 

     // make them bounce 
     boolean finished = false; 
     while(!finished) { 
      myCanvas.wait(50);   // small delay 
      ball.move(); 
      ball2.move(); 
      // stop once ball has travelled a certain distance on x axis 
      if(ball.getXPosition() >= 550 && ball2.getXPosition() >= 550) { 
       finished = true; 
      } 
     } 
     ball.erase(); 
     ball2.erase(); 
    } 
    public void drawFrame() 
    { 
     Dimension size=myCanvas.getFrameSize(); 

     myCanvas.setSize(size.width, size.height); 
     // myCanvas.setVisible(true); 
     Rectangle rect = new Rectangle(20, 20, size.width-40, size.height-40); 
     myCanvas.draw(rect); 

    } 
} 

为了得到帧大小我包括在画布类的方法getFrameSize如下

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

/** 
* Class Canvas - a class to allow for simple graphical 
* drawing on a canvas. 
* 
* @author Michael Kolling (mik) 
* @author Bruce Quig 
* 
* @version 2008.03.30 
*/ 

public class Canvas 
{ 
    private JFrame frame; 
    private CanvasPane canvas; 
    private Graphics2D graphic; 
    private Color backgroundColor; 
    private Image canvasImage; 

    /** 
    * Create a Canvas with default height, width and background color 
    * (300, 300, white). 
    * @param title title to appear in Canvas Frame  
    */ 
    public Canvas(String title) 
    { 
     this(title, 300, 300, Color.white);   
    } 

    /** 
    * Create a Canvas with default background color (white). 
    * @param title title to appear in Canvas Frame 
    * @param width the desired width for the canvas 
    * @param height the desired height for the canvas 
    */ 
    public Canvas(String title, int width, int height) 
    { 
     this(title, width, height, Color.white); 
    } 

    /** 
    * Create a Canvas. 
    * @param title title to appear in Canvas Frame 
    * @param width the desired width for the canvas 
    * @param height the desired height for the canvas 
    * @param bgClour the desired background color of the canvas 
    */ 
    public Canvas(String title, int width, int height, Color bgColor) 
    { 
     frame = new JFrame(); 
     canvas = new CanvasPane(); 
     frame.setContentPane(canvas); 
     frame.setTitle(title); 
     canvas.setPreferredSize(new Dimension(width, height)); 
     backgroundColor = bgColor; 
     frame.pack(); 
    } 

    /** 
    * Set the canvas visibility and brings canvas to the front of screen 
    * when made visible. This method can also be used to bring an already 
    * visible canvas to the front of other windows. 
    * @param visible boolean value representing the desired visibility of 
    * the canvas (true or false) 
    */ 
    public void setVisible(boolean visible) 
    { 
     if(graphic == null) { 
      // first time: instantiate the offscreen image and fill it with 
      // the background color 
      Dimension size = canvas.getSize(); 
      canvasImage = canvas.createImage(size.width, size.height); 
      graphic = (Graphics2D)canvasImage.getGraphics(); 
      graphic.setColor(backgroundColor); 
      graphic.fillRect(0, 0, size.width, size.height); 
      //graphic.setColor(Color.black); 
     } 
     frame.setVisible(true); 
    } 

    /** 
    * Provide information on visibility of the Canvas. 
    * @return true if canvas is visible, false otherwise 
    */ 
    public boolean isVisible() 
    { 
     return frame.isVisible(); 
    } 

    /** 
    * Draw the outline of a given shape onto the canvas. 
    * @param shape the shape object to be drawn on the canvas 
    */ 
    public void draw(Shape shape) 
    { 
     graphic.draw(shape); 
     canvas.repaint(); 
    } 

    /** 
    * Fill the internal dimensions of a given shape with the current 
    * foreground color of the canvas. 
    * @param shape the shape object to be filled 
    */ 
    public void fill(Shape shape) 
    { 
     graphic.fill(shape); 
     canvas.repaint(); 
    } 

    /** 
    * Fill the internal dimensions of the given circle with the current 
    * foreground color of the canvas. 
    */ 
    public void fillCircle(int xPos, int yPos, int diameter) 
    { 
     Ellipse2D.Double circle = new Ellipse2D.Double(xPos, yPos, diameter, diameter); 
     fill(circle); 
    } 

    /** 
    * Fill the internal dimensions of the given rectangle with the current 
    * foreground color of the canvas. This is a convenience method. A similar 
    * effect can be achieved with the "fill" method. 
    */ 
    public void fillRectangle(int xPos, int yPos, int width, int height) 
    { 
     fill(new Rectangle(xPos, yPos, width, height)); 
    } 

    /** 
    * Erase the whole canvas. 
    */ 
    public void erase() 
    { 
     Color original = graphic.getColor(); 
     graphic.setColor(backgroundColor); 
     Dimension size = canvas.getSize(); 
     graphic.fill(new Rectangle(0, 0, size.width, size.height)); 
     graphic.setColor(original); 
     canvas.repaint(); 
    } 

    /** 
    * Erase the internal dimensions of the given circle. This is a 
    * convenience method. A similar effect can be achieved with 
    * the "erase" method. 
    */ 
    public void eraseCircle(int xPos, int yPos, int diameter) 
    { 
     Ellipse2D.Double circle = new Ellipse2D.Double(xPos, yPos, diameter, diameter); 
     erase(circle); 
    } 

    /** 
    * Erase the internal dimensions of the given rectangle. This is a 
    * convenience method. A similar effect can be achieved with 
    * the "erase" method. 
    */ 
    public void eraseRectangle(int xPos, int yPos, int width, int height) 
    { 
     erase(new Rectangle(xPos, yPos, width, height)); 
    } 

    /** 
    * Erase a given shape's interior on the screen. 
    * @param shape the shape object to be erased 
    */ 
    public void erase(Shape shape) 
    { 
     Color original = graphic.getColor(); 
     graphic.setColor(backgroundColor); 
     graphic.fill(shape);    // erase by filling background color 
     graphic.setColor(original); 
     canvas.repaint(); 
    } 

    /** 
    * Erases a given shape's outline on the screen. 
    * @param shape the shape object to be erased 
    */ 
    public void eraseOutline(Shape shape) 
    { 
     Color original = graphic.getColor(); 
     graphic.setColor(backgroundColor); 
     graphic.draw(shape); // erase by drawing background color 
     graphic.setColor(original); 
     canvas.repaint(); 
    } 

    /** 
    * Draws an image onto the canvas. 
    * @param image the Image object to be displayed 
    * @param x  x co-ordinate for Image placement 
    * @param y  y co-ordinate for Image placement 
    * @return returns boolean value representing whether the image was 
    *   completely loaded 
    */ 
    public boolean drawImage(Image image, int x, int y) 
    { 
     boolean result = graphic.drawImage(image, x, y, null); 
     canvas.repaint(); 
     return result; 
    } 

    /** 
    * Draws a String on the Canvas. 
    * @param text the String to be displayed 
    * @param x  x co-ordinate for text placement 
    * @param y  y co-ordinate for text placement 
    */ 
    public void drawString(String text, int x, int y) 
    { 
     graphic.drawString(text, x, y); 
     canvas.repaint(); 
    } 

    /** 
    * Erases a String on the Canvas. 
    * @param text  the String to be displayed 
    * @param x  x co-ordinate for text placement 
    * @param y  y co-ordinate for text placement 
    */ 
    public void eraseString(String text, int x, int y) 
    { 
     Color original = graphic.getColor(); 
     graphic.setColor(backgroundColor); 
     graphic.drawString(text, x, y); 
     graphic.setColor(original); 
     canvas.repaint(); 
    } 

    /** 
    * Draws a line on the Canvas. 
    * @param x1 x co-ordinate of start of line 
    * @param y1 y co-ordinate of start of line 
    * @param x2 x co-ordinate of end of line 
    * @param y2 y co-ordinate of end of line 
    */ 
    public void drawLine(int x1, int y1, int x2, int y2) 
    { 
     graphic.drawLine(x1, y1, x2, y2); 
     canvas.repaint(); 
    } 

    /** 
    * Sets the foreground color of the Canvas. 
    * @param newColor the new color for the foreground of the Canvas 
    */ 
    public void setForegroundColor(Color newColor) 
    { 
     graphic.setColor(newColor); 
    } 

    /** 
    * Returns the current color of the foreground. 
    * @return the color of the foreground of the Canvas 
    */ 
    public Color getForegroundColor() 
    { 
     return graphic.getColor(); 
    } 

    /** 
    * Sets the background color of the Canvas. 
    * @param newColor the new color for the background of the Canvas 
    */ 
    public void setBackgroundColor(Color newColor) 
    { 
     backgroundColor = newColor; 
     graphic.setBackground(newColor); 
    } 

    /** 
    * Returns the current color of the background 
    * @return the color of the background of the Canvas 
    */ 
    public Color getBackgroundColor() 
    { 
     return backgroundColor; 
    } 

    /** 
    * changes the current Font used on the Canvas 
    * @param newFont new font to be used for String output 
    */ 
    public void setFont(Font newFont) 
    { 
     graphic.setFont(newFont); 
    } 

    /** 
    * Returns the current font of the canvas. 
    * @return  the font currently in use 
    **/ 
    public Font getFont() 
    { 
     return graphic.getFont(); 
    } 

    /** 
    * Sets the size of the canvas. 
    * @param width new width 
    * @param height new height 
    */ 
    public void setSize(int width, int height) 
    { 
     canvas.setPreferredSize(new Dimension(width, height)); 
     Image oldImage = canvasImage; 
     canvasImage = canvas.createImage(width, height); 
     graphic = (Graphics2D)canvasImage.getGraphics(); 
     graphic.drawImage(oldImage, 0, 0, null); 

     frame.pack(); 
    } 

    /** 
    * Returns the size of the canvas. 
    * @return  The current dimension of the canvas 
    */ 
    public Dimension getSize() 
    { 
     return canvas.getSize(); 
    } 
    public Dimension getFrameSize() 
    { 
     Dimension size=frame.getSize(); 
     return size; 
    } 

    /** 
    * Waits for a specified number of milliseconds before finishing. 
    * This provides an easy way to specify a small delay which can be 
    * used when producing animations. 
    * @param milliseconds the number 
    */ 
    public void wait(int milliseconds) 
    { 
     try 
     { 
      Thread.sleep(milliseconds); 
     } 
     catch (InterruptedException e) 
     { 
      // ignoring exception at the moment 
     } 
    } 

    /************************************************************************ 
    * Inner class CanvasPane - the actual canvas component contained in the 
    * Canvas frame. This is essentially a JPanel with added capability to 
    * refresh the image drawn on it. 
    */ 
    private class CanvasPane extends JPanel 
    { 
     public void paint(Graphics g) 
     { 
      g.drawImage(canvasImage, 0, 0, null); 
     } 
    } 
} 

正如这里有必要执行PROGRAME我包括第三类也

import java.awt.*; 
import java.awt.geom.*; 

/** 
* Class BouncingBall - a graphical ball that observes the effect of gravity. The ball 
* has the ability to move. Details of movement are determined by the ball itself. It 
* will fall downwards, accelerating with time due to the effect of gravity, and bounce 
* upward again when hitting the ground. 
* 
* This movement can be initiated by repeated calls to the "move" method. 
* 
* @author Bruce Quig 
* @author Michael Kolling (mik) 
* @author David J. Barnes 
* 
* @version 2008.03.30 
*/ 

public class BouncingBall 
{ 
    private static final int GRAVITY = 3; // effect of gravity 

    private int ballDegradation = 2; 
    private Ellipse2D.Double circle; 
    private Color color; 
    private int diameter; 
    private int xPosition; 
    private int yPosition; 
    private final int groundPosition;  // y position of ground 
    private Canvas canvas; 
    private int ySpeed = 1;    // initial downward speed 

    /** 
    * Constructor for objects of class BouncingBall 
    * 
    * @param xPos the horizontal coordinate of the ball 
    * @param yPos the vertical coordinate of the ball 
    * @param ballDiameter the diameter (in pixels) of the ball 
    * @param ballColor the color of the ball 
    * @param groundPos the position of the ground (where the wall will bounce) 
    * @param drawingCanvas the canvas to draw this ball on 
    */ 
    public BouncingBall(int xPos, int yPos, int ballDiameter, Color ballColor, 
         int groundPos, Canvas drawingCanvas) 
    { 
     xPosition = xPos; 
     yPosition = yPos; 
     color = ballColor; 
     diameter = ballDiameter; 
     groundPosition = groundPos; 
     canvas = drawingCanvas; 
    } 

    /** 
    * Draw this ball at its current position onto the canvas. 
    **/ 
    public void draw() 
    { 
     canvas.setForegroundColor(color); 
     canvas.fillCircle(xPosition, yPosition, diameter); 
    } 

    /** 
    * Erase this ball at its current position. 
    **/ 
    public void erase() 
    { 
     canvas.eraseCircle(xPosition, yPosition, diameter); 
    }  

    /** 
    * Move this ball according to its position and speed and redraw. 
    **/ 
    public void move() 
    { 
     // remove from canvas at the current position 
     erase(); 

     // compute new position 
     ySpeed += GRAVITY; 
     yPosition += ySpeed; 
     xPosition +=2; 

     // check if it has hit the ground 
     if(yPosition >= (groundPosition - diameter) && ySpeed > 0) { 
      yPosition = (int)(groundPosition - diameter); 
      ySpeed = -ySpeed + ballDegradation; 
     } 

     // draw again at new position 
     draw(); 
    }  

    /** 
    * return the horizontal position of this ball 
    */ 
    public int getXPosition() 
    { 
     return xPosition; 
    } 

    /** 
    * return the vertical position of this ball 
    */ 
    public int getYPosition() 
    { 
     return yPosition; 
    } 
} 

随着溶液我已经想出用于我面临两个问题

1通过使用鼠标和执行并条机方法改变所述帧的大小后,将exersice一个矩形作为旨在绘制但是在drawFrame方法被执行超过它使用鼠标改变的大小之后,框架会稍微膨胀。这是因为我认为通过frame.size()获得的宽度和高度甚至包括了边框的大小。所以当myCanvas.setSize (宽度,高度)myCanvas将展开为包含边框大小的框架的大小。 如何阻止myCanvas扩展到框架边界以外

2 myCanvas的扩展部分的背景颜色以黑色显示如何使其变为白色?

+0

壁挂式的,作业是一个新的。 – Welbog 2009-06-10 19:11:43

回答

0

为您的JFrame添加ComponentListener(您可以使用ComponentAdapter类并重写componentResized方法)。

frame.addComponentListener(new ComponentAdapter() { 
     @Override 
     public void componentResized(ComponentEvent e) { 
      // TODO handle the change 
     } 
    }); 

每当您的jframe更改大小时,您还需要重新绘制图形。问题是你的canvasImage的大小是固定的,所以你将不得不创建一个新的图像(使用调整大小的窗格)并将原始图形复制到新图像中。这将是一个相当沉重的操作

0

如果你扩展JComponent,你使用BorderLayout添加一个JFrame,你会得到免费的调整大小通知。

2

如从this answer的图片(如下)所示,不同的布局管理器将会或不会考虑组件的首选尺寸。那个不会“伸展”的孩子的组成部分。

还要注意,在JPanelJComponent做风俗画的时候,你想覆盖JPanel因此面板的getPreferredSize()将有较好大小。您对pack()在框架上调用,将尊重首选大小

public class DrawPanel extends JPanel { 
    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(500, 500); 
    } 
} 

enter image description here