??xml version="1.0" encoding="utf-8" standalone="yes"?>
通常的做法是调用JFileChooser.showXXX()Ҏ(gu)昄文g选取对话框ƈ且选择一个文件后Q点?font face="Courier New">Approve 按钮Q默认情况下标有 "Open" ?"Save"Q?/font>Q?/font>当对话框关闭后用JFileChooser.getSelectedFile()Ҏ(gu)得到选取的文Ӟ或用JFileChooser.getSelectedFiles()取得选取的文件数l)(j)Q然后再对被选取的文件有效性进行验证(例如Q文件的文g名是否合法、选取的\径下是否已有同名文g存在{等Q,如果验证不通过Q需要再ơ打开文g选择对话框进行选取?br />
昄Q验证没有通过的情况下Q文仉取对话框被反复的打开和关闭,影响用户体验?br />
我现在介l一个方法,在点M(jin)文g选取对话框上?font face="Courier New">Approve 按钮后,文g选取对话框关闭前寚w取的文件进行验证,如果验证没有通过Q那么对话框不关闭,直接q行下一ơ选择?br />
查看JFileChooser的APIQ可以发现这样一个方?public void approveSelection() Q这个方法会(x)在用户单?Approve 按钮时由 UI 调用此方法。导致用等?APPROVE_SELECTION
的命令字W串Ȁ发一个操作事件?br />
那么Q我们现在可以选择l承JFileChooser再覆写这个方法,对选中文g的有效性验证写入这个方法中Q只有当验证通过时才调用类的approveSelection() 完成文g选取Q否则直接返回,l箋(hu)选择新的文g?br />
下面是我写的一个demo以供参考:(x)
import java.io.File;
import javax.swing.JOptionPane;
/**
(tng)* ?JFileChooser 中进行文仉证的技?br /> (tng)* @author Chen Wei
(tng)* @email chenwei.mobi@gmail.com
(tng)*/
public class JFileChooserDemo extends javax.swing.JFileChooser{
(tng) (tng) (tng)
(tng) (tng) (tng) public void approveSelection(){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) File file = getSelectedFile();
(tng) (tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) // 验证文g名是否合?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) if (!validateFileName(file.getName())) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) JOptionPane.showMessageDialog(getParent(), "文g名不能包含下列Q何字W之一Q\n \\ / : * ? \" < > |");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) }else{
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) super.approveSelection();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) }
(tng) (tng) (tng) }
(tng) (tng) (tng)
(tng) (tng) (tng) /**
(tng) (tng) (tng) (tng) * 验证输入字符串参数是否ؓ(f)有效文g名?br /> (tng) (tng) (tng) (tng) * @param name 待验证的文g名字W串?br /> (tng) (tng) (tng) (tng) * @return 通过验证Q文件名无效q回 falseQ有效返?true?br /> (tng) (tng) (tng) (tng) */
(tng) (tng) (tng) public static boolean validateFileName(String name) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) if (name.indexOf('\\') != -1 || name.indexOf('/') != -1 ||
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) name.indexOf(':') != -1 || name.indexOf('*') != -1 ||
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) name.indexOf('?') != -1 || name.indexOf('"') != -1 ||
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) name.indexOf('<') != -1 || name.indexOf('>') != -1 ||
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) name.indexOf('|') != -1) {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return false;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) } else {
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) return true;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) }
(tng) (tng) (tng) }
(tng) (tng) (tng)
(tng) (tng) (tng) public static void main(String[] args){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) JFileChooserDemo chooser = new JFileChooserDemo();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) chooser.showOpenDialog(null);
(tng) (tng) (tng) }
}
E序q行截图Q?br />
使用q个Ҏ(gu)前需要先图像文件从盘?sh)读C?java.awt.image.BufferedImage 对象中,我们可以?J2SE 包含?ImageIO 库?/p>
AWT 使用 ImageProducer / ImagConsumer 模式Q支持加载和昄 GIF 囑փ文g格式?JPEG 囑փ文g格式。因为图像的加蝲和显C是异步方式q行的,所以有大量加蝲和显C的技术?BR>
?AWT 中,提供?jin)一?java.awt.Image cRjava.awt.Image cM表一个图像对象被作ؓ(f)参数传递给其他用来昄和处理图像的其他 AWT 对象使用。例如,通过调用 Graphics.drawImage(java.awt.Image, int, int, ImageObserver) Ҏ(gu)Q可以在lg中画出图像?BR>
java.awt.Image 是一个定义方法的抽象c,它定义的Ҏ(gu)提供的对囑փ信息的访问。而创建和处理囑փ的基本结构则?java.awt.image 包中。注意,q里不要?java.awt.Image 发生h?BR>
AWT (tng) 加蝲和显C图像用的?ImageProducer / ImagConsumer 模式Q我们必M(jin)?个术语,ImageProducerQ图像生产者)(j)QImageConsumerQ图像消费者)(j)和ImageObserverQ图像观察者)(j)?BR>
ImageProducer 负责生囑փ的位QImagConsumer 接受囑փ的位QImageObserver 监视 ImageProducer 的图像生产过E。ImageProducer 生传递给 ImagConsumer 与图像相关的位。因为图像生产过E是异步q行的,q不是一ơ性生产所有图像位Q所以当 ImageProducer 加蝲囑փӞImageObserver 用来监视它的q展情况。因?java.awt.Component 实现?ImageObserver 接口Q所?AWT 中的每个lg都可以是ImageObserverQ当一个给定的 ImageProducer q行异步操作Ӟq个 ImageObserver 可以选择是否被更新。java.awt.image 包ؓ(f) ImageProducerQImagConsumer ?ImageObserver 都定义了(jin)接口?BR>
ImageProducer
和图像相关的位ƈ不存储在 java.awt.Image 中,每个囑փ都维护一个和一?ImageProducer (tng)的关联。这?ImageProducer (tng)的责L生囑փ的位q将它们传送给 ImagConsumerQ用于过滤该囑փ?BR>
java.awt.image软g包中QFilteredImageSourceQ被qo(h)的图像源Q和 MemoryImageSourceQ内存的囑փ源)(j)实现?ImageProducer (tng) 接口Q是 ImageProducer (tng)?BR>
ImagConsumer
java.awt.image软g包中QImageFilterQ图像过滤器Q和 PixelGrabberQ像素抓取器Q实C(jin) ImagConsumer 接口Q是 ImagConsumer?BR>
ImageProducer (tng)?ImagConsumer 的详l介l请阅读 使用 ImageProducer (tng) / ImagConsumer q行囑փqo(h)
ImageObserver
ImageObserver接口中,定义?jin)一个常数集合和一个方法:(x)
public boolean imageUpdate(image img, int flags, int x, int y, int width, int height);
ImageObserver的常?/TD> | |
标志 | 含义 |
ABORT | 囑փ加蝲被中?/TD> |
ALLBITS | 所有的位都已加载给囑փ |
ERROR | 在加载过E中发生错误 |
FRAMEBITS | 多囑փ的一个被传送,一般用?SPAN lang=en-us>GIF |
HEIGHT | 囑փ的高度已l可?/TD> |
PROPERTIES | 囑փ的属性已l可?/TD> |
SOMEBITS | 囑փ的羃攑֏?sh)的多个位已l可?/TD> |
WIDTH | 囑փ的宽度已l可?/TD> |
输出l果Q?BR>image width = -1 height = -1
囑փ的高度和宽度只有在图像被完全加蝲后才是有效的Q输出结果说?java.awt.image 相关的图像位在需要之前不被生产?BR>
?Q图像异步生?/P>
输出l果Q?BR>drawing (tng)image...
false
drawing (tng)image...
false
drawing (tng)image...
false
drawing (tng)image...
true
输出l果说明lg作ؓ(f) ImageObserver Q监?ImageProducer 异步生囑փQ一旦有新的囑փ位被生时就重绘囑փQ图像完全加载后 drawImage() Ҏ(gu)q回 true?BR>
?Q重?ImageObserver ?imageUpdate() Ҏ(gu)Q在囑փ完全加蝲前不调用 repaint()
?Q重q?Component.update() Ҏ(gu)Q被调用时不清除背景囑փQ直接调?paint() Ҏ(gu)l制囑փQ消除闪?/P>
(tng)
囑փ的加载和昄是异步进行的Q图? 的生产?ImageProducer)传递给囑փ的消费?ImageConsumer)一个与囑փ相关的位Q因为图像的生q程是一个异步行为,所? AWT 也提供一个图像观?ImageObserver)Q用来监视图像生产者的囑փ生q程?/font>
因ؓ(f) java.awt.Component 实现 ImageObserver 接口Q所?AWT 中每个构仉是ImageObserver Q当一个给定的 ImageProducer 采取异步操作Ӟq个 ImageObserver 可以选择是否被更新?/font>
现在看一个例子:(x)
当这?Applet W一ơ被调用Ӟ打印出下面的结果:(x)
drawing (tng)image...
false
drawing (tng)image...
false
drawing (tng)image...
false
drawing (tng)image...
true
?
行结果说?drawImage() 在第一ơ被调用Ӟ没有囑փ被加载,drawImage() 只是向和囑փ相关?ImageProducer
注册 ImageObserverQ图像被完全加蝲?drawImage() Ҏ(gu)q回 false 直到囑փ被完全加载返?true?/font>
?drawImage() q回之后Q只要有囑փ的新的部分被加蝲QImageObserver 中的 imageUpdate() Ҏ(gu)׃(x)被调用。当 ImageObserver ?AWT 构gӞComponent.imageUpdate() 调用 repaint() Ҏ(gu)清除构g背景q调?paint() Ҏ(gu)重绘刚刚得到的图像位。重复@环,ImageProducer 加蝲囑փ的下一块,调用 ImageObserver ?imageUpdate()。当囑փ被完全加载时QImageProducer 停止调用 ImageObserver ?imageUpdate()Q@环中断?/font>
load -> imageUpdate() -> repaint() -> update() -> paint()
{待囑փ的完全加?br />
上面的例子介l了(jin)囑փ的异步加载,现在介绍2个方法囑փ完全加蝲前不昄?br />
·重蝲 ImageObserver 中的 imageUpdate() Ҏ(gu)Q其在囑փ完全加蝲前不调用 repaint()?/font>
import
(tng)java.awt.Graphics;
import
(tng)java.awt.Image;
public
(tng)
class
(tng)I(yng)mageTestAppletWithUpdate
(tng) (tng) (tng) (tng)
extends
(tng)Applet (tng){
(tng) (tng)
private
(tng)I(yng)mage (tng)im;
(tng) (tng)
public
(tng)
void
(tng)init() (tng){
(tng) (tng) (tng) (tng)im (tng)
=
(tng)getImage(getCodeBase(), (tng)
"
lena.jpg
"
);
(tng) (tng)}
(tng) (tng)
public
(tng)
void
(tng)paint(Graphics (tng)g) (tng){
(tng) (tng) (tng) (tng)g.drawImage(im, (tng)
0
, (tng)
0
, (tng)
this
);
(tng) (tng)}
(tng) (tng)
public
(tng)
boolean
(tng)imageUpdate(Image (tng)image, (tng)
int
(tng)flags, (tng)
int
(tng)x, (tng)
int
(tng)y, (tng)
int
(tng)w, (tng)
int
(tng)h) (tng){
(tng) (tng) (tng) (tng)System.out.println(
"
imageUpdate():x=
"
(tng)
+
(tng)x (tng)
+
(tng)
"
,y=
"
(tng)
+
(tng)y (tng)
+
(tng)
"
,w=
"
(tng)
+
(tng)w (tng)
+
(tng)
"
,h=
"
(tng)
+
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)h);
(tng) (tng) (tng) (tng)
if
(tng)( (tng)(flags (tng)
&
(tng)ALLBITS) (tng)
==
(tng)
0
) (tng){
(tng) (tng) (tng) (tng) (tng) (tng)
return
(tng)
true
; (tng)
//
(tng)need (tng)more (tng)updates
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)
else
(tng){
(tng) (tng) (tng) (tng) (tng) (tng)repaint();
(tng) (tng) (tng) (tng) (tng) (tng)
return
(tng)
false
; (tng)
//
(tng)image (tng)is (tng)fully (tng)loaded
(tng) (tng) (tng) (tng)}
(tng) (tng)}
}
使用 java.awt.MediaTracker c跟t图像的加蝲Q不必重?imageUpdate() Ҏ(gu)?/font>
import
(tng)java.applet.Applet;
import
(tng)java.awt.Graphics;
import
(tng)java.awt.Image;
import
(tng)java.awt.MediaTracker;
public
(tng)
class
(tng)I(yng)mageTestAppletWithMediaTracker
(tng) (tng) (tng) (tng)
extends
(tng)Applet (tng){
(tng) (tng)
private
(tng)I(yng)mage (tng)im;
(tng) (tng)
public
(tng)
void
(tng)init() (tng){
(tng) (tng) (tng) (tng)im (tng)
=
(tng)getImage(getCodeBase(), (tng)
"
lena.jpg
"
);
(tng) (tng) (tng) (tng)MediaTracker (tng)tracker (tng)
=
(tng)
new
(tng)MediaTracker(
this
);
(tng) (tng) (tng) (tng)tracker.addImage(im, (tng)
0
);
(tng) (tng) (tng) (tng)
try
(tng){
(tng) (tng) (tng) (tng) (tng) (tng)tracker.waitForID(
0
);
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)
catch
(tng)(InterruptedException (tng)e) (tng){
(tng) (tng) (tng) (tng) (tng) (tng)e.printStackTrace();
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)System.out.print(
"
Image (tng)width (tng)= (tng)
"
(tng)
+
(tng)im.getWidth(
this
));
(tng) (tng) (tng) (tng)System.out.println(
"
height (tng)= (tng)
"
(tng)
+
(tng)im.getHeight(
this
));
(tng) (tng)}
(tng) (tng)
public
(tng)
void
(tng)paint(Graphics (tng)g) (tng){
(tng) (tng) (tng) (tng)g.drawImage(im, (tng)
0
, (tng)
0
, (tng)
this
);
(tng) (tng)}
}
我们可以把?java.awt.MediaTracker cd囑փ完全加蝲的方法包装成一个实用方?/font>
(tng) (tng) (tng)* (tng)使用 (tng)java.awt.MediaTracker (tng)图像完全加载?br /> (tng) (tng) (tng)* (tng)
@param
(tng)component (tng)Component
(tng) (tng) (tng)* (tng)
@param
(tng)img (tng)I(yng)mage
(tng) (tng) (tng)
*/
(tng) (tng)
public
(tng)
static
(tng)
void
(tng)waitForImage(Component (tng)component, (tng)I(yng)mage (tng)img) (tng){
(tng) (tng) (tng) (tng)MediaTracker (tng)tracker (tng)
=
(tng)
new
(tng)MediaTracker(component);
(tng) (tng) (tng) (tng)
try
(tng){
(tng) (tng) (tng) (tng) (tng) (tng)tracker.addImage(img, (tng)
0
);
(tng) (tng) (tng) (tng) (tng) (tng)tracker.waitForID(
0
);
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)
catch
(tng)(InterruptedException (tng)ex) (tng){
(tng) (tng) (tng) (tng) (tng) (tng)ex.printStackTrace();
(tng) (tng) (tng) (tng)}
(tng) (tng)}