package
book.net;
import
java.awt.BorderLayout;
import
java.awt.event.ActionEvent;
import
java.awt.event.ActionListener;
import
java.awt.event.WindowAdapter;
import
java.awt.event.WindowEvent;
import
java.beans.PropertyChangeEvent;
import
java.beans.PropertyChangeListener;
import
java.io.File;
import
java.io.IOException;
import
java.net.MalformedURLException;
import
java.net.URL;
import
java.util.ArrayList;
import
javax.swing.JButton;
import
javax.swing.JEditorPane;
import
javax.swing.JFileChooser;
import
javax.swing.JFrame;
import
javax.swing.JLabel;
import
javax.swing.JMenu;
import
javax.swing.JMenuBar;
import
javax.swing.JMenuItem;
import
javax.swing.JOptionPane;
import
javax.swing.JScrollPane;
import
javax.swing.JTextField;
import
javax.swing.JToolBar;
import
javax.swing.event.HyperlinkEvent;
import
javax.swing.event.HyperlinkListener;
import
javax.swing.filechooser.FileFilter;
/**
* 实现一个简单的Web浏览器,支持HTML和HTM页面的显示。使用了JEditorPane组件
**/
public
class
WebBrowser
extends
JFrame
implements
HyperlinkListener,
PropertyChangeListener {
/**下面是使用的Swing组件**/
JEditorPane textPane;
JLabel messageLine;
JTextField urlField;
JFileChooser fileChooser;
JButton backButton;
JButton forwardButton;
java.util.List history =
new
ArrayList();
int
currentHistoryPage = -
1
;
public
static
final
int
MAX_HISTORY =
50
;
static
int
numBrowserWindows =
0
;
static
boolean
exitWhenLastWindowClosed =
false
;
String home =
"http://www.google.com"
;
/**
* 构造函数
*/
public
WebBrowser() {
super
(
"WebBrowser"
);
textPane =
new
JEditorPane();
textPane.setEditable(
false
);
textPane.addHyperlinkListener(
this
);
textPane.addPropertyChangeListener(
this
);
this
.getContentPane().add(
new
JScrollPane(textPane),
BorderLayout.CENTER);
messageLine =
new
JLabel(
" "
);
this
.getContentPane().add(messageLine, BorderLayout.SOUTH);
this
.initMenu();
this
.initToolbar();
WebBrowser.numBrowserWindows++;
this
.addWindowListener(
new
WindowAdapter() {
public
void
windowClosing(WindowEvent e) {
close();
}
});
}
/**
* 初始化菜单栏
*/
private
void
initMenu(){
JMenu fileMenu =
new
JMenu(
"文件"
);
fileMenu.setMnemonic(
'F'
);
JMenuItem newMenuItem =
new
JMenuItem(
"新建"
);
newMenuItem.setMnemonic(
'N'
);
newMenuItem.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
newBrowser();
}
});
JMenuItem openMenuItem =
new
JMenuItem(
"打开"
);
openMenuItem.setMnemonic(
'O'
);
openMenuItem.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
openLocalPage();
}
});
JMenuItem closeMenuItem =
new
JMenuItem(
"关闭窗口"
);
closeMenuItem.setMnemonic(
'C'
);
closeMenuItem.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
close();
}
});
JMenuItem exitMenuItem =
new
JMenuItem(
"退出"
);
exitMenuItem.setMnemonic(
'E'
);
exitMenuItem.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
exit();
}
});
fileMenu.add(newMenuItem);
fileMenu.add(openMenuItem);
fileMenu.add(closeMenuItem);
fileMenu.add(exitMenuItem);
JMenu helpMenu =
new
JMenu(
"帮助"
);
fileMenu.setMnemonic(
'H'
);
JMenuItem aboutMenuItem =
new
JMenuItem(
"关于"
);
aboutMenuItem.setMnemonic(
'A'
);
helpMenu.add(aboutMenuItem);
JMenuBar menuBar =
new
JMenuBar();
menuBar.add(fileMenu);
menuBar.add(helpMenu);
this
.setJMenuBar(menuBar);
}
/**
* 初始化工具栏
*/
private
void
initToolbar(){
backButton =
new
JButton(
"后退"
);
backButton.setEnabled(
false
);
backButton.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
back();
}
});
forwardButton =
new
JButton(
"前进"
);
forwardButton.setEnabled(
false
);
forwardButton.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
forward();
}
});
JButton refreshButton =
new
JButton(
"刷新"
);
refreshButton.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
reload();
}
});
JButton homeButton =
new
JButton(
"主页"
);
homeButton.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
home();
}
});
JToolBar toolbar =
new
JToolBar();
toolbar.add(backButton);
toolbar.add(forwardButton);
toolbar.add(refreshButton);
toolbar.add(homeButton);
urlField =
new
JTextField();
urlField.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
displayPage(urlField.getText());
}
});
toolbar.add(
new
JLabel(
" 地址:"
));
toolbar.add(urlField);
this
.getContentPane().add(toolbar, BorderLayout.NORTH);
}
/**
* 设置浏览器是否在所有窗口都关闭时退出
* @param b
*/
public
static
void
setExitWhenLastWindowClosed(
boolean
b) {
exitWhenLastWindowClosed = b;
}
/**
* 设置主页
* @param home 新主页
*/
public
void
setHome(String home) {
this
.home = home;
}
/**
* 获取主页
*/
public
String getHome() {
return
home;
}
/**
* 访问网址URL
*/
private
boolean
visit(URL url) {
try
{
String href = url.toString();
startAnimation(
"加载 "
+ href +
"..."
);
textPane.setPage(url);
this
.setTitle(href);
urlField.setText(href);
return
true
;
}
catch
(IOException ex) {
stopAnimation();
messageLine.setText(
"不能打开页面:"
+ ex.getMessage());
return
false
;
}
}
/**
* 浏览器打开URL指定的页面,如果成功,将URL放入历史列表中
*/
public
void
displayPage(URL url) {
if
(visit(url)) {
history.add(url);
int
numentries = history.size();
if
(numentries > MAX_HISTORY+
10
) {
history = history.subList(numentries-MAX_HISTORY, numentries);
numentries = MAX_HISTORY;
}
currentHistoryPage = numentries -
1
;
if
(currentHistoryPage >
0
){
backButton.setEnabled(
true
);
}
}
}
/**
* 浏览器打开字符串指定的页面
* @param href 网址
*/
public
void
displayPage(String href) {
try
{
if
(!href.startsWith(
"http://"
)){
href =
"http://"
+ href;
}
displayPage(
new
URL(href));
}
catch
(MalformedURLException ex) {
messageLine.setText(
"错误的网址: "
+ href);
}
}
/**
* 打开本地文件
*/
public
void
openLocalPage() {
if
(fileChooser ==
null
) {
fileChooser =
new
JFileChooser();
FileFilter filter =
new
FileFilter() {
public
boolean
accept(File f) {
String fn = f.getName();
if
(fn.endsWith(
".html"
) || fn.endsWith(
".htm"
)){
return
true
;
}
else
{
return
false
;
}
}
public
String getDescription() {
return
"HTML Files"
;
}
};
fileChooser.setFileFilter(filter);
fileChooser.addChoosableFileFilter(filter);
}
int
result = fileChooser.showOpenDialog(
this
);
if
(result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile( );
try
{
displayPage(selectedFile.toURL());
}
catch
(MalformedURLException e) {
e.printStackTrace();
}
}
}
/**
* 后退,回到前一页
*/
public
void
back() {
if
(currentHistoryPage >
0
){
visit((URL)history.get(--currentHistoryPage));
}
backButton.setEnabled((currentHistoryPage >
0
));
forwardButton.setEnabled((currentHistoryPage < history.size()-
1
));
}
/**
* 前进,回到后一页
*/
public
void
forward() {
if
(currentHistoryPage < history.size( )-
1
){
visit((URL)history.get(++currentHistoryPage));
}
backButton.setEnabled((currentHistoryPage >
0
));
forwardButton.setEnabled((currentHistoryPage < history.size()-
1
));
}
/**
* 重新加载当前页面
*/
public
void
reload() {
if
(currentHistoryPage != -
1
) {
textPane.setDocument(
new
javax.swing.text.html.HTMLDocument());
visit((URL)history.get(currentHistoryPage));
}
}
/**
* 显示主页
*/
public
void
home() {
displayPage(getHome());
}
/**
* 打开新的浏览器窗口
*/
public
void
newBrowser() {
WebBrowser b =
new
WebBrowser();
b.setSize(
this
.getWidth(),
this
.getHeight());
b.setVisible(
true
);
}
/**
* 关闭当前窗口,如果所有窗口都关闭,则根据exitWhenLastWindowClosed属性,
* 判断是否退出应用程序
*/
public
void
close() {
this
.setVisible(
false
);
this
.dispose();
synchronized
(WebBrowser.
class
) {
WebBrowser.numBrowserWindows--;
if
((numBrowserWindows==
0
) && exitWhenLastWindowClosed){
System.exit(
0
);
}
}
}
/**
* 退出应用程序
*/
public
void
exit() {
if
((JOptionPane.showConfirmDialog(
this
,
"你确定退出Web浏览器?"
,
"退出"
,
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)){
System.exit(
0
);
}
}
/**
* 实现HyperlinkListener接口。处理超连接事件
*/
public
void
hyperlinkUpdate(HyperlinkEvent e) {
HyperlinkEvent.EventType type = e.getEventType();
if
(type == HyperlinkEvent.EventType.ACTIVATED) {
displayPage(e.getURL());
}
else
if
(type == HyperlinkEvent.EventType.ENTERED) {
messageLine.setText(e.getURL().toString());
}
else
if
(type == HyperlinkEvent.EventType.EXITED) {
messageLine.setText(
" "
);
}
}
/**
* 实现PropertyChangeListener接口。处理属性改变事件。
* 显示HTML面板textPane的属性改变时,由该方法处理。
* 当textPane调用完setPage方法时,page属性便改变了。
*/
public
void
propertyChange(PropertyChangeEvent e) {
if
(e.getPropertyName().equals(
"page"
)) {
stopAnimation();
}
}
String animationMessage;
int
animationFrame =
0
;
String[] animationFrames =
new
String[] {
"-"
,
"\\"
,
"|"
,
"/"
,
"-"
,
"\\"
,
"|"
,
"/"
,
","
,
"."
,
"o"
,
"0"
,
"O"
,
"#"
,
"*"
,
"+"
};
/**
* 新建一个Swing的定时器,每个125毫秒更新一次状态栏标签的文本
*/
javax.swing.Timer animator =
new
javax.swing.Timer(
125
,
new
ActionListener() {
public
void
actionPerformed(ActionEvent e) {
animate();
}
});
/**
* 显示动画的当前帧到状态栏标签上,并将帧索引后移
*/
private
void
animate() {
String frame = animationFrames[animationFrame++];
messageLine.setText(animationMessage +
" "
+ frame);
animationFrame = animationFrame % animationFrames.length;
}
/**
* 启动动画
*/
private
void
startAnimation(String msg) {
animationMessage = msg;
animationFrame =
0
;
animator.start();
}
/**
* 停止动画
*/
private
void
stopAnimation() {
animator.stop();
messageLine.setText(
" "
);
}
public
static
void
main(String[] args)
throws
IOException {
WebBrowser.setExitWhenLastWindowClosed(
true
);
WebBrowser browser =
new
WebBrowser();
browser.setSize(
800
,
600
);
browser.setVisible(
true
);
browser.displayPage(browser.getHome());
}
}