如何让Jpanel扩展到JFrame的大小?
下面的代码来自 Michale Kolling 和 David J Barnes 所著的《objects First With Java》一书,以下是书中的一个练习(例如 5.49)。例如:改进你的drawFrame方法以自动适应当前画布的大小。为此,您需要了解如何使用 Dimension 类的对象。
在下面的 BallDemo 类中,有一个名为drameFrame 的方法。创建该方法的目的是在窗口内绘制一个 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);
}
}
为了获取框架大小,我在 Canvas 类中包含了一个 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);
}
}
}
因为执行程序是必要的,所以我包含了第三个类也
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使用鼠标更改框架的大小并执行drawFrame方法后,按预期绘制了矩形但框架在drawFrame方法后扩展了一点执行的尺寸大于使用鼠标更改的尺寸。这是因为我假设通过frame.size()获得的宽度和高度甚至包括边框尺寸。所以当执行myCanvas.setSize(width, height)时myCanvas展开框架的尺寸,也包括边框尺寸。 如何阻止 myCanvas 扩展到框架边框之外
2 myCanvas 扩展部分的背景色显示为黑色 如何将其变为白色?
The below code is from the book objects First With Java By Michale Kolling and David J Barnes and the following is an exercise (ex 5.49) from the book.The ex is : Improve your drawFrame method to adapt automatically to the current canvas's size.To do this you need to find out how to make use of an objectof class Dimension.
In the following class BallDemo there is a method called drameFrame.The intention of creating the method is to draw a Rectangle 20 pixels inside the window and redraw the rectangle when the size of the frame is changed
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);
}
}
To get the frame size I included a method getFrameSize in the Canvas class as below
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);
}
}
}
As it is neccessary to execute the programe I am including the third class also
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;
}
}
With the solution I have come up for the exersice I am faced with two problems
1 After changing the size of the frame by using the mouse and executing the drawFrame method a rectangle is drawn as intended But the frame expands a little after drawFrame method is executed more than the size it was changed using the mouse.This is because I suppose the width and the height obtained through frame.size() includes even the border size.So when myCanvas.setSize(width, height) is executed myCanvas expands to size of the frame which includes the border size also.
How can I stop myCanvas from expanding beyond the border of the frame
2 The background color of the expanded portion of myCanvas appears in black how is it possible to make it white?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如这个答案中的图片(下图)所示,不同的布局管理器会或不会'尊重组件的首选尺寸。 不会“拉伸”子组件的组件。
另请注意,在
JPanel
或JComponent
上进行自定义绘制时,您需要覆盖JPanel
的getPreferredSize()
> 因此面板将具有首选尺寸。 您对框架上的pack()
的调用将遵循首选尺寸As seen in the image (below) from this answer, different layout managers will or won't respect the preferred sizes of component. The one's that don't will "stretch" the the child component.
Also note, when doing custom painting on
JPanel
orJComponent
, you want to override thegetPreferredSize()
of theJPanel
so the panel will have a preferred size. Your call topack()
on the frame, will respect that preferred size为您的 JFrame 添加一个 ComponentListener(您可以使用 ComponentAdapter 类并重写 componentResized 方法)。
每次 jframe 改变大小时,您还需要重新绘制图形。 问题是你的canvasImage是固定大小的,所以你必须创建一个新图像(使用调整大小的窗格)并将原始图形复制到新图像中。 这将是一个相当繁重的操作
for your JFrame, add a ComponentListener (you can use the ComponentAdapter class and override the componentResized method).
Everytime your jframe changes size, you need to also redraw your graphic. the problem is your canvasImage is of a fixed size, so you're going to have to create a new image (with the resized pane) and copy your original graphic into the new image. this is going to be a rather heavy operation
如果您扩展 JComponent,并使用 BorderLayout 将其添加到 JFrame,您将获得免费调整大小通知。
If you extend JComponent you add it the a JFrame using BorderLayout, you get free resize notification.