zoukankan      html  css  js  c++  java
  • 完整的Java简单浏览器

    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组件**/
         
        // 显示HTML的面板
        JEditorPane textPane;
        // 最底下的状态栏
        JLabel messageLine;
        // 网址URL输入栏
        JTextField urlField;
        // 文件选择器,打开本地文件时用
        JFileChooser fileChooser;
         
        // 后退和前进 按钮
        JButton backButton;
        JButton forwardButton;
     
        // 保存历史记录的列表
        java.util.List history = new ArrayList();
        // 当前页面的在历史记录列表中位置
        int currentHistoryPage = -1
        // 当历史记录超过MAX_HISTORY时,清除旧的历史
        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");
     
            // 新建显示HTML的面板,并设置它不可编辑
            textPane = new JEditorPane();
            textPane.setEditable(false);
     
            // 注册事件处理器,用于超连接事件。
            textPane.addHyperlinkListener(this);
            // 注册事件处理器,用于处理属性改变事件。当页面加载结束时,触发该事件
            textPane.addPropertyChangeListener(this);
     
            // 将HTML显示面板放入主窗口,居中显示
            this.getContentPane().add(new JScrollPane(textPane),
                                      BorderLayout.CENTER);
     
            // 创建状态栏标签,并放在主窗口底部
            messageLine = new JLabel(" ");
            this.getContentPane().add(messageLine, BorderLayout.SOUTH);
     
            // 初始化菜单和工具栏
            this.initMenu();
            this.initToolbar();
             
            // 将当前打开窗口数增加1
            WebBrowser.numBrowserWindows++;
             
            // 当关闭窗口时,调用close方法处理
            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();
                // 启动动画,当网页被加载完成时,触发propertyChanged事件,动画停止。
                startAnimation("加载 " + href + "...");
                 
                // 设置显示HTML面板的page属性为待访问的URL,
                // 在这个方法里,将打开URL,将URL的流显示在textPane中。
                // 当完全打开后,该方法才结束。
                textPane.setPage(url);
                 
                // 页面打开后,将浏览器窗口的标题设为URL
                this.setTitle(href); 
                // 网址输入框的内容也设置为URL
                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)) {
                // 如果成功,则将URL放入历史列表中。
                history.add(url);
                int numentries = history.size();
                if (numentries > MAX_HISTORY+10) {
                    history = history.subList(numentries-MAX_HISTORY, numentries);
                    numentries = MAX_HISTORY;
                }
                // 将当前页面下标置为numentries-1
                currentHistoryPage = numentries - 1;
                // 如果当前页面不是第一个页面,则可以后退,允许点击后退按钮。
                if (currentHistoryPage > 0){
                    backButton.setEnabled(true);
                }
            }
        }
     
        /**
         * 浏览器打开字符串指定的页面
         * @param href  网址
         */
        public void displayPage(String href) {
            try {
                // 默认为HTTP协议
                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();
                // 使用文件过滤器限制只能够HTML和HTM文件
                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);
                // 只允许选择HTML和HTM文件
                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));
            }
            // 如果当前页面下标大于0,允许后退
            backButton.setEnabled((currentHistoryPage > 0));
            // 如果当前页面下标不是最后,允许前进
            forwardButton.setEnabled((currentHistoryPage < history.size()-1));
        }
        /**
         * 前进,回到后一页
         */
        public void forward() {
            if (currentHistoryPage < history.size( )-1){
                visit((URL)history.get(++currentHistoryPage));
            }
            // 如果当前页面下标大于0,允许后退
            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();
            // 将当前打开窗口数减1。
            // 如果所有窗口都已关闭,而且exitWhenLastWindowClosed为真,则退出
            // 这里采用了synchronized关键字,保证线程安全
            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")) {
                // 页面加载完毕时,textPane的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());
        }
    }
  • 相关阅读:
    PAT 1010. 一元多项式求导 (25)
    PAT 1009. 说反话 (20) JAVA
    PAT 1009. 说反话 (20)
    PAT 1007. 素数对猜想 (20)
    POJ 2752 Seek the Name, Seek the Fame KMP
    POJ 2406 Power Strings KMP
    ZOJ3811 Untrusted Patrol
    Codeforces Round #265 (Div. 2) 题解
    Topcoder SRM632 DIV2 解题报告
    Topcoder SRM631 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/martin-roger/p/5479341.html
Copyright © 2011-2022 走看看