因为SWT的ImageLoader支持读写以上所有格式的图片,所以实现起来比较简单。主要解决了两个问题。第一个问题是播放GIF动画,通过 ImageLoader读入GIF的所有帧以及间隔时间,然后用Display.timerExec实现Timer播放。第二个问题是对图片的 Scrollbar支持以及pack支持。SWT.H_SCROLL和SWT.V_SCROLL 虽然加上了滚动条,但是不起作用,需要监听滚动条的SWT.Selection事件。另外,加上滚动条后,pack无法得到大小,不能正确的pack。需 要重载computeSize。
/**
* 负责显示各种格式的图片 * *
@author
喜来乐哈哈
*/
public
class
ImageViewer
extends
Canvas {
protected
Point origin
=
new
Point(
0
,
0
);
protected
Image image;
protected
ImageData[] imageDatas;
protected
Image[] images;
protected
int
current;
private
int
repeatCount;
private
Runnable animationTimer;
private
ScrollBar hBar;
private
ScrollBar vBar;
private
Color bg;
private
Display display;
public
ImageViewer(Composite parent) {
super
(parent, SWT.NO_BACKGROUND
|
SWT.NO_REDRAW_RESIZE
|
SWT.V_SCROLL
|
SWT.H_SCROLL); hBar
=
getHorizontalBar(); vBar
=
getVerticalBar(); bg
=
getBackground(); display
=
getDisplay(); addListeners(); }
public
void
setImage(ImageData imageData) { checkWidget(); stopAnimationTimer();
this
.image
=
new
Image(display, imageData);
this
.imageDatas
=
null
;
this
.images
=
null
; redraw(); }
/**
*
@param
repeatCount 0 forever
*/
public
void
setImages(ImageData[] imageDatas,
int
repeatCount) { checkWidget();
this
.image
=
null
;
this
.imageDatas
=
imageDatas;
this
.repeatCount
=
repeatCount; convertImageDatasToImages(); startAnimationTimer(); redraw(); } @Override
public
Point computeSize(
int
wHint,
int
hHint,
boolean
changed) { checkWidget(); Image image
=
getCurrentImage();
if
(image
!=
null
) { Rectangle rect
=
image.getBounds(); Rectangle trim
=
computeTrim(
0
,
0
, rect.width, rect.height);
return
new
Point(trim.width, trim.height); }
return
new
Point(wHint, hHint); } @Override
public
void
dispose() {
if
(image
!=
null
) image.dispose();
if
(images
!=
null
)
for
(
int
i
=
0
; i
gc.fillRectangle(rect.width,
0
, marginWidth, client.height); }
int
marginHeight
=
client.height
-
rect.height;
if
(marginHeight
>
0
) { gc.fillRectangle(
0
, rect.height, client.width, marginHeight); } }
void
addListeners() { hBar.addListener(SWT.Selection,
new
Listener() {
public
void
handleEvent(Event arg0) { hscroll(); } }); vBar.addListener(SWT.Selection,
new
Listener() {
public
void
handleEvent(Event arg0) { vscroll(); } }); addListener(SWT.Resize,
new
Listener() {
public
void
handleEvent(Event e) { resize(); } }); addListener(SWT.Paint,
new
Listener() {
public
void
handleEvent(Event e) { paint(e); } }); }
void
hscroll() { Image image
=
getCurrentImage();
if
(image
!=
null
) {
int
hSelection
=
hBar.getSelection();
int
destX
=
-
hSelection
-
origin.x; Rectangle rect
=
image.getBounds(); scroll(destX,
0
,
0
,
0
, rect.width, rect.height,
false
); origin.x
=
-
hSelection; } }
void
vscroll() { Image image
=
getCurrentImage();
if
(image
!=
null
) {
int
vSelection
=
vBar.getSelection();
int
destY
=
-
vSelection
-
origin.y; Rectangle rect
=
image.getBounds(); scroll(
0
, destY,
0
,
0
, rect.width, rect.height,
false
); origin.y
=
-
vSelection; } }
void
resize() { Image image
=
getCurrentImage();
if
(image
==
null
)
return
; Rectangle rect
=
image.getBounds(); Rectangle client
=
getClientArea(); hBar.setMaximum(rect.width); vBar.setMaximum(rect.height); hBar.setThumb(Math.min(rect.width, client.width)); vBar.setThumb(Math.min(rect.height, client.height));
int
hPage
=
rect.width
-
client.width;
int
vPage
=
rect.height
-
client.height;
int
hSelection
=
hBar.getSelection();
int
vSelection
=
vBar.getSelection();
if
(hSelection
>=
hPage) {
if
(hPage
=
vPage) {
if
(vPage
ImageData id
=
imageDatas[i]; images[i]
=
new
Image(display, width, height); GC gc
=
new
GC(images[i]);
//
Do the transition from the previous image.
switch
(transition) {
case
SWT.DM_FILL_NONE:
case
SWT.DM_UNSPECIFIED:
//
Start from last image.
gc.drawImage(images[i
-
1
],
0
,
0
);
break
;
case
SWT.DM_FILL_PREVIOUS:
//
Start from second last image.
gc.drawImage(images[i
-
2
],
0
,
0
);
break
;
default
:
//
DM_FILL_BACKGROUND or anything else,
//
just fill with default background.
gc.setBackground(bg); gc.fillRectangle(
0
,
0
, width, height);
break
; }
//
Draw the current image and clean up.
Image img
=
new
Image(display, id); gc.drawImage(img,
0
,
0
, id.width, id.height, id.x, id.y, id.width, id.height); img.dispose(); gc.dispose();
//
Compute the next transition.
//
Special case: Can't do DM_FILL_PREVIOUS on the
//
second image since there is no "second last"
//
image to use.
transition
=
id.disposalMethod;
if
(i
==
0
&&
transition
==
SWT.DM_FILL_PREVIOUS) transition
=
SWT.DM_FILL_NONE; } } Image getCurrentImage() {
if
(image
!=
null
)
return
image;
if
(images
==
null
)
return
null
;
return
images[current]; }
void
startAnimationTimer() {
if
(images
==
null
||
images.length
if
(isDisposed())
return
; current
=
(current
+
1
)
%
images.length; redraw();
if
(current
+
1
==
images.length
&&
repeatCount
!=
0
&&
--
repeatCount
public
static
void
main(String[] args) { Display display
=
new
Display();
final
Shell shell
=
new
Shell(display); ImageViewer ic
=
new
ImageViewer(shell); shell.setLayout(
new
FillLayout()); FileDialog dialog
=
new
FileDialog(shell, SWT.OPEN); dialog.setText(
"
Open an image file or cancel
"
); String string
=
dialog.open(); ImageLoader loader
=
new
ImageLoader(); ImageData[] imageDatas
=
loader.load(string);
if
(imageDatas.length
==
0
)
return
;
else
if
(imageDatas.length
==
1
) { ic.setImage(imageDatas[
0
]); }
else
{ ic.setImages(imageDatas, loader.repeatCount); } ic.pack(); shell.pack(); shell.open();
while
(
!
shell.isDisposed()) {
if
(
!
display.readAndDispatch()) display.sleep(); } display.dispose(); } }
在对GIF图片的支持上,Swing要做的好很多,一句label.setIcon(new ImageIcon(name))就搞定GIF动画了。
转载请保留http://www.blogjava.net/xilaile/archive/2007/04/10/109547.html
|