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());
}
}