平时看英文文档或者查询资料的时候,遇到了不懂的单词,就要去百度,然后就会很麻烦。于是就想到用Java写一个及时翻译的小工具!
预期的实现效果:
双击选中一个单词,按下Ctrl+C进行复制
然后马上显示出对应单词的中文翻译
首先基本思路是这样的:
- 首先获取系统剪切板的内容
- 将该内容发送到网页上,然后获取网页的源码,查找到对应的中文解释
- 将中文翻译显示出来
以上就是基本的思路!但是实际操作的时候还是遇到了很大的困难的。
先写两个接口
得到剪切板的内容
这个并不是很困难,毕竟java有提供对应的API,代码如下:
package translate;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
public class ClipboradUtils {
protected static String getClipboardText() throws Exception{
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();//获取系统剪贴板
// 获取剪切板中的内容
Transferable clipT = clip.getContents(null);
if (clipT != null) {
// 检查内容是否是文本类型
if (clipT.isDataFlavorSupported(DataFlavor.stringFlavor))
return (String)clipT.getTransferData(DataFlavor.stringFlavor);
}
return null;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
以上是放在一个工具类,做成静态函数方便调用!
获取网页源码
首先想到是就是去百度翻译
我们在这里翻译单词 blue
我们看地址栏http://fanyi.baidu.com/?aldtype=16047#en/zh/blue
,刚好我们要翻译的单词就在最后,所以只要爬取页面http://fanyi.baidu.com/?aldtype=16047#en/zh/待查单词
的源代码,然后做一些筛选就可以了!
然后事情进展的却并不是那么的顺利,百度的这个应该是为了防止爬取,所以翻译的操作应该是Dom操作,源代码上面毫无翻译痕迹。
这个方法就终止了。
然后想到的是百度翻译是否有开放接口
果然,百度翻译提供了开放的接口,但是貌似要收费。
http://api.fanyi.baidu.com/api/trans/product/index
当然,我建议大家用这个方法,毕竟人家公司也不容易,而且功能也相对很丰富。
但是,如果真的不想花钱就不行了吗?答案是否定的!
意外收获
我在百度直接搜索一个单词的是否发现也会出现对应的翻译!如下:
然后查看一下源代码,搜索蓝色
,果然,源代码上面是有翻译结果的(偷笑)。
而且对应的翻译内容就在<span class="op_dict_text2">
和</span>
之间!
百度搜索的url对应的是http://www.baidu.com/s?wd="搜索内容"
于是就可以把获取翻译内容的工具类写好了,代码如下:
package translate;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class GetHtmlContentUtils {
private final static String PreUrl="http://www.baidu.com/s?wd="; //百度搜索URL
private final static String TransResultStartFlag="<span class=\"op_dict_text2\">"; //翻译开始标签
private final static String TransResultEndFlag="</span>"; //翻译结束标签
public static String getTranslateResult(String urlString) throws Exception { //传入要搜索的单词
URL url = new URL(PreUrl+urlString); //生成完整的URL
// 打开URL
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// 得到输入流,即获得了网页的内容
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String preLine="";
String line;
int flag=1;
// 读取输入流的数据,并显示
String content=""; //翻译结果
while ((line = reader.readLine()) != null) { //获取翻译结果的算法
if(preLine.indexOf(TransResultStartFlag)!=-1&&line.indexOf(TransResultEndFlag)==-1){
content+=line.replaceAll(" | ", "")+"\n"; //去电源代码上面的半角以及全角字符
flag=0;
}
if(line.indexOf(TransResultEndFlag)!=-1){
flag=1;
}
if(flag==1){
preLine=line;
}
}
return content;//返回翻译结果
}
}
- 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
再写一个窗体界面
注:有了上面的核心算法,下面的其实都随意实现了!
界面实现
我设计的窗体界面如下:
简单说一下界面布局:最上面一个JTextField
和JCheckBox
,下面是JTextArea
。
简单说一下各个控件的作用:
JTextField:显示待翻译的单词
JCheckBox:表示是从剪切板获取单词还是自己直接输入
JTextArea:显示翻译结果
实现思路
界面已经实现完成了,那么思路是什么呢?
我的思路是这样的:
- 开启一个线程,将JTextField里面的值不断设置为剪切板里面的值
- 如果JTextField里面的值改变了(剪切板的值改变了,也就是选中复制了新的单词),调用GetHtmlContentUtils 里面的方法获取翻译的结果,并显示!
对应代码如下:
package translate;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class MainFrame extends JFrame implements Runnable {
private JTextField srcContentTextField; // 记录剪切板的内容
private JTextArea resContentTextField; // 记录翻译的内容
private JCheckBox translateFlag; //标记单词的获取来源
//选中:手动输入 未选中:剪切板获取
private Container topContainer;
public MainFrame() {//初始化控件
srcContentTextField = new JTextField(10);
resContentTextField = new JTextArea();
translateFlag = new JCheckBox();
topContainer = new Container();
}
public void setMinWindowLayout() {
// TODO Auto-generated method stub
//布局设置
resContentTextField.setBorder(new LineBorder(new java.awt.Color(127, 157, 185), 1, false));
this.setLayout(new BorderLayout());
this.add(this.resContentTextField);
translateFlag.setToolTipText("手动输入取词");
topContainer.setLayout(new BorderLayout());
topContainer.add(srcContentTextField, BorderLayout.CENTER);
topContainer.add(translateFlag, BorderLayout.EAST);
this.add(this.topContainer, BorderLayout.NORTH);
this.setResizable(false);
translateFlag.addActionListener(new ActionListener() {//设置JCheckBox的监听
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (translateFlag.isSelected()) {
translateFlag.setToolTipText("自动复制取词"); //设置提示
} else {
translateFlag.setToolTipText("手动输入取词");
}
}
});
//监听JTextField里面内容改变的事件
srcContentTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent arg0) {
}
@Override
public void insertUpdate(DocumentEvent arg0) { //内容改变
try {
//调用接口获取翻译结果
String result = GetHtmlContentUtils.getTranslateResult(srcContentTextField.getText());
if (result == "")
result = "!Sorry,未找到该词!";
resContentTextField.setText(result);//显示翻译结果
} catch (Exception e) {
// TODO Auto-generated catch block
resContentTextField.setText("!Sorry,未找到该词!");
}
}
@Override
public void removeUpdate(DocumentEvent arg0) {
}
});
this.validate();
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
if (!translateFlag.isSelected()) { //如果JCheckBox没有被选中,则从剪切板获取单词
try {
String content = ClipboradUtils.getClipboardText();
srcContentTextField.setText(getSimpleWord(content));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static String getSimpleWord(String content) {//去掉切板里面的一些特殊字符
return content.replace(".", "").replace(",", "")
.replace("'", "").replace(":", "")
.replace(";", "").trim();
}
}
- 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
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
接下来就是main函数了,代码如下:
package translate;
import javax.swing.JFrame;
public class TranslateTool {
public static void main(String[] args) {
MainFrame mainFrame = new MainFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setBounds(300, 200, 400, 300);
mainFrame.setVisible(true);
mainFrame.setAlwaysOnTop(true);//设置在最顶层
mainFrame.setMinWindowLayout();
Thread t = new Thread(mainFrame);
t.start(); //开启线程
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
程序运行结果
随手翻译了下 public 关键字,感觉还是可以的!