5.实现绘制图像的功能
这是你的类真正的核心功能。你将需要确保你的类在图像只部分可见时,能够只画出其自身的一部分, 还要确保其在设置、加载、修改或者编辑时能够重新绘制其自身. 依赖于你扩展的父类,你可能需要重写和绘制图像有关的几个方法. Swing 的 JComponent 为我们做了大部分的重要工作 . JImageComponent 重写了 paint(java.awt.Graphics) 方法, 还有两个 paintImmediately() 方法. 注意力主要需要放在由组件的可见矩形所指定的图像的绘制上. 这将会在讨论用于滚动容器中的功能的实现时解释. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
@Override
public void paint(Graphics g) {
if ( this .bufferedImage == null ) {
return ;
}
Rectangle rectangle = this .getVisibleRect();
paintImmediately(g, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
};
@Override
public void paintImmediately( int x, int y, int width, int height) {
if ( this .bufferedImage == null ) {
return ;
}
this .paintImmediately( super .getGraphics(), x, y, width, height);
}
@Override
public void paintImmediately(Rectangle rectangle) {
if ( this .bufferedImage == null ) {
return ;
}
this .paintImmediately( super .getGraphics(), rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}
|
简单起见,JImageComponent 会有一个私有的方法 ,paintImmediately(Graphics, int, int, int, int) ,来做实际上的图形的绘制. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /**
* Paints the image onto the component.
*
* @param g
* The <code>Graphics object of the component onto which the
* image region will be painted.
* @param x
* The x value of the region to be painted.
* @param y
* The y value of the region to be painted.
* @param width
* The width of the region to be painted.
* @param height
* The width of the region to be painted.
*/
private void paintImmediately(Graphics g, int x, int y, int width, int height) {
if ( this .bufferedImage == null ) {
return ;
}
int imageWidth = this .bufferedImage.getWidth();
int imageHeight = this .bufferedImage.getHeight();
if (x >= imageWidth || y >= imageHeight) {
return ;
}
int x1 = x < 0 ? 0 : x;
int y1 = y < 0 ? 0 : y;
int x2 = x + width - 1 ;
int y2 = y + height - 1 ;
if (x2 >= imageWidth) {
x2 = imageWidth - 1 ;
}
if (y2 >= imageHeight) {
y2 = imageHeight - 1 ;
}
g.drawImage( this .bufferedImage, x1, y1, x2, y2, x1, y1, x2, y2, null );
}
|
6. 实现当处在一个滚动容器中时的组件绘制
需要解决的一个挑战是,如何绘制一张被用于滚动容器中的图像. 例如,一个开发者可能会想要将一张尺寸超出可视边界的图像放到一个 JScrollPane 容器中. JImageComponent通过做下面三件事情来解决了这个问题: 你可能需要实现在你想要确保你的组件在滚动容器中可以被正确渲染时,能提供带有适当布局细节的布局管理器的功能. JImageComponent 通过重写如下的方法提供必要的布局详细: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /**
* Returns the height of the image.
*/
@Override
public int getHeight() {
if ( this .bufferedImage == null ) {
return 0 ;
}
return this .bufferedImage.getHeight();
}
/**
* Returns the size of the image.
*/
@Override
public Dimension getPreferredSize() {
if ( this .bufferedImage == null ) {
return new Dimension( 0 , 0 );
}
return new Dimension( this .bufferedImage.getWidth(), this .bufferedImage.getHeight());
}
/**
* Returns the size of the image.
*/
@Override
public Dimension getSize() {
if ( this .bufferedImage == null ) {
return new Dimension( 0 , 0 );
}
return new Dimension( this .bufferedImage.getWidth(), this .bufferedImage.getHeight());
}
/**
* Returns the width of the image.
*/
@Override
public int getWidth() {
if ( this .bufferedImage == null ) {
return 0 ;
}
return this .bufferedImage.getWidth();
}
|
7. 实现编辑图像的功能
在编辑图像时许多的实例将会比持续的修改图像来得更加高效. 一个例子就是当你想要展示一个动画的时候,修改每张动画图像改变的区域,会比在内存中创建一张图像并在组件中对其进行设置更加高效. JImageComponent 通过提供一个访问其 BufferedImage的方法,以及一个访问图像的 Graphics 对象的方法来允许这个功能. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /**
* Returns the <code>BufferedImage object for the image.
*
* @return The buffered image.
*/
public BufferedImage getBufferedImage() {
return this .bufferedImage;
}
/**
* Returns the Graphics object for the image.
*/
@Override
public Graphics getGraphics() {
return this .imageGraphics;
}
|
JImageComponent 还提供了一个用来调整/转换图像的方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | /**
* Resizes the image to the given dimensions and type.
* Note that the image is "cropped" from the left top corner).
*
* @param width
* The new width of the image.
* @param height
* The new height of the image.
* @param imageType
* The new image type (<code>BufferedImage type)
* @see type java.awt.image.BufferedImage#BufferedImage(int, int, int)
*/
public void resize( int width, int height, int imageType) {
if ( this .bufferedImage == null ) {
setBufferedImage( new BufferedImage(width, height, imageType));
return ;
}
BufferedImage tempImage = new BufferedImage(width, height, imageType);
int w = this .bufferedImage.getWidth();
int h = this .bufferedImage.getHeight();
if (width < w) {
w = width;
}
if (height < h) {
h = height;
}
if ( this .bufferedImage.getType() == imageType) {
Graphics g = tempImage.getGraphics();
g.drawImage( this .bufferedImage, 0 , 0 , w, h, null );
}
else {
for ( int y = 0 ; y < h; y++) {
for ( int x = 0 ; x < w; x++) {
tempImage.setRGB(x, y, this .bufferedImage.getRGB(x, y));
}
}
}
setBufferedImage(tempImage);
}
|
|