Swing中多线程操作UI

Categories: Java; Tagged with: ; @ February 4th, 2009 0:17

通常 Swing 不是线程安全的。除非另行说明,否则所有 Swing 组件及相关类都必须在事件调度线程上访问。

由于Swing不是线程安全的, 因此在实际操作过程中, 应避免通过多线程来操作UI. 在必要时, 应注意要将控件转移到事件调度线程。转移控件和开始处理 Swing 的首选方法是使用 invokeLater

简单的实践:

在如下小程序中, 通过最上方或最下方的Parse 都可以针对某文件或URL进行解析, 并解析出文件中含有的Email, 并归类但因在中间的TextArea中.

在按下Parse时, 将创建一个新的线程, 进行操作.

image

onParse: 为每个请求创建新的线程:

	/** 响应Parse点击或textFilePath回车 - 为每个请求创建一个单独线程 */
	private ActionListener onParse = new ActionListener() {
		public void actionPerformed(ActionEvent e){
			//通过事件来源来判断读取哪个filePath;
			if(e.getSource().equals(buttonParse) || e.getSource().equals(textFilePath)) {
				filePathOnAction = textFilePath.getText();
			}else if(e.getSource().equals(buttonParse2) || e.getSource().equals(textFilePath2)) {
				filePathOnAction = textFilePath2.getText();
			}

			Thread threadParseEmail = new Thread(){ //将为每个请求创造一个线程
				@Override
				public void run() {
					parseEmail(swui.filePathOnAction);
				}
			};
			threadParseEmail.setName("ParseEmail-" + threadParseEmail.getName());
			threadParseEmail.start();

			log.debug("Parse clicked");	//使用log, 便于分辨线程
		}
	};

	 //解析文件, 将ParseEmail返回信息打印到textOutPut中
	private void parseEmail(final String filePath) {
		//buttonParse.setEnabled(false);
		log.info("正在解析");
		labelInfoMessage.setText("正在解析");
		if(labelImage.getIcon() == null) {
			labelImage.setIcon(imageParseing);
		}else {
			labelImage.setVisible(true);
		}
		//TODO Update UI code is put to the AWT-Event Queue so that only the AWT-Event Queue thread executes the UI update code.
		// Other threads may update UI directly but problems may arise in many cases.
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				log.info("Update UI code is put to the AWT-Event Queue so that only the AWT-Event Queue thread executes the UI update code");
				try {
					if(filePath.startsWith("http")) {
						URL romatefile = new URL(filePath);
						textOutput.setText(pe.parseEmailAndReturnDomain(romatefile.openStream()));

					}else {
						textOutput.setText(pe.parseEmailAndReturnDomain(filePath));
					}
					labelInfoMessage.setText("解析完毕");

				} catch (Exception e) {
					log.debug("IO Exception - File does not exist");
					labelInfoMessage.setText("文件不存在, 请确地址是否正确.");
					textOutput.setText("文件不存在, 请确地址是否正确.");
				}

				labelImage.setVisible(false);
			}
		});
	}

log信息:

[AWT-EventQueue-0] DEBUG com.maill.parser.test.UI – Parse clicked  //UI线程

[ParseEmail-Thread-2] INFO  com.maill.parser.test.UI – 正在解析 //表明已经创建新的线程

[AWT-EventQueue-0] INFO  com.maill.parser.test.UI – Update UI code is put to the AWT-Event Queue so that only the AWT-Event Queue thread executes the UI update code //将Thread-2中操作UI的部分交由UI线程处理.

=============================

类似的, 在SWT中, 不允许由非UI线程进行UI操作, 否则将会有Exception抛出. 而在Swing中, 不会抛出任何Exception, 但会产生不安全隐患.

SWT中的event loop flow:

2009-2-13-19-49-17

上图中的Read adn dispatch:

2009-2-13-19-48-32

StringBuilder 小结

Categories: Java; Tagged with: ; @ February 1st, 2009 15:54
//----------------------以下待删除--------------
//	TODO 学习后删除;
	public static String getTestString() {
		StringBuilder sb = new StringBuilder();//新建一个SB
		sb.append("Print: ");
		for(int i=0; i < 10; i++) {
			if(i != 0) {
				sb.append(", ");
				// s += ", "; //BAD!
			}
			sb.append(i);
			// s += i; //BAD!
		}
		sb.append("a").append("b").append("C").
		append("w"); 
		return sb.toString();
		System.out.println(sb.toString());
		// return s; // BAD!
		// return "Id: " + id; // 简单情况下使用"+"链接, OK
	}

Java I/O 操作

Categories: Java February 1st, 2009 15:49

处理一个本地文件 或是一个InputStream

	public String parseEmail(String fileName) throws IOException{ 
		java.io.File file  = new java.io.File(fileName);
		if(file.isFile()) {
			return parseEmail(new FileInputStream(fileName));
		}else {
			throw new IOException();
		}
	}
	
	public String parseEmail(InputStream in) throws IOException{
		// InputStream in = new FileInputStream(fileName);
		InputStreamReader reader;
		
		reader = new InputStreamReader(in);
		
		BufferedReader br = new BufferedReader(reader);
		
		String data1;
		//按行读
		while((data1= br.readLine()) != null) {
		System.out.println(data1);
}
		

待续…

Java正则表达式使用笔记

Categories: Java; Tagged with: ; @ February 1st, 2009 15:40

1. 编写并测试正则表达式.

使用工具:

Eclipse 正则表达式书写测试插件 – 基于java.util.regex

 

2.

//定义正则表达式

//定义正则表达式
	private static final String REGEX_EMAIL = "([\\w\\.-]{1,})@(([\\w-]{1,}\\.)+[a-zA-Z]{2,})";	//Group1, 2;

 

3. 使用

Pattern patternEmail = Pattern.compile(REGEX_EMAIL);
java.util.regex.Matcher matcherEmail = patternEmail.matcher(data); 

        while (matcherEmail.find()) {
            String pb = matcherEmail.group(1);
            String pa = matcherEmail.group(2).toLowerCase(); 
,............
        }

其中data为string类型

 

该正则表达式将取得data中所有的email地址.

其中group1为@前的字符 group2为@之后的domain.

Java中使用参数选择 – Use Preferences in Java

Categories: Java; Tagged with: ; @ February 1st, 2009 0:30

API: http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/java/util/prefs/Preferences.html

需求: 某文件解析器, 设定解析的默认文件, 在关闭时将最后一次解析的路径保存, 再次打开时, 取出上次解析文件之路径.

用法:

取得针对此包的用户和系统参数选择的Preferences对象:

private Preferences userPrefs = Preferences.userNodeForPackage(SwingUI.class);
private Preferences sysPrefs = Preferences.systemNodeForPackage(SwingUI.class);

查询参数选择值[默认值]:

public void initPrefs() {
    filePath = userPrefs.get("filePath", http://liguoliang.com/email.txt);
}

关闭之前保存最后一次解析文件的路径:

监听关闭事件:

        /**//* 使用匿名类添加一个窗口监听器 */
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
            	savePrefs();
            	System.out.println(
                    "Exit when Closed event");
                //退出应用程序
                System.exit(0);
            }
        });

保存数据

public void savePrefs() {
    userPrefs.put("filePath", textFilePath.getText());
    try {
        userPrefs.flush();
    } catch (BackingStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

如图: 第一次运行时, 默认路径: http://liguoliang.com/email.txt

image

在File中输入: http://xjst.org
image

点击关闭程序, 再次运行:

image

此时默认路径为上一次解析的http://xjst.org/

Newer Posts <-> Older Posts



// Proudly powered by Apache, PHP, MySQL, WordPress, Bootstrap, etc,.