• 精简版web浏览器


    import javax.swing.JFrame;
    import javax.swing.JEditorPane;
    import javax.swing.event.HyperlinkListener;
    import java.beans.PropertyChangeListener;
    import javax.swing.event.HyperlinkEvent;
    import java.beans.PropertyChangeEvent;
    import javax.swing.JEditorPane;
    import javax.swing.JLabel;
    import javax.swing.JTextField;
    import javax.swing.JFileChooser;
    import javax.swing.JScrollPane;
    import java.awt.BorderLayout;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import javax.swing.JButton;
    import java.util.ArrayList;
    import java.net.MalformedURLException;
    import java.net.URL;
    import javax.swing.JMenu;
    import javax.swing.JMenuItem;
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    import javax.swing.filechooser.FileFilter;
    import java.io.File;
    import javax.swing.JOptionPane;
    import javax.swing.JMenuBar;
    import javax.swing.text.html.HTMLDocument;
    import javax.swing.JToolBar;
    import java.io.IOException;
    import java.awt.Dimension;
    import java.awt.Toolkit;
    import java.awt.event.KeyEvent;
    import java.util.Date;
    import java.text.SimpleDateFormat;
    /*
    【问题1】:点击"主页"按钮后,再次点击,下面文本提示一直在加载,没有返回结果,也没有返回超时
    【问题2】:"打开"菜单功能未实现--is ok!
    【问题3】:页面链接的 输入类型(HyperlinkEvent.EventType.ENTERED)不起作用--可以支持http://www.baidu.com、http://www.hao123.com
    【问题4】:菜单中的快捷键如何使用?--先使用Alt+快捷键进入菜单,接着使用菜单项快捷键打开菜单项
    【问题5】:存放打开页面的队列满了是什么情况?
    */
    
    /**
    JFrame:顶级容器
    JPanel:普通容器
    JFrame的结构从里到外(按照图层的叠加顺序)依次为:frame->rootpane->layeredpane->contentpane->menuBar(optional)->glasspane
        frame
            rootpane
                layeredpane
                    contentpane:默认是JPanel,一般的组件都放在JPanel
                    menuBar
                glasspane:默认是透明的 
    */
    public class WebBrowser extends JFrame implements HyperlinkListener,PropertyChangeListener{
        /**
        JEditorPane的最主要功能在于展现不同类型的文件格式内容
        第一种是纯文本类型,其类型的表示法为"text/plain",这种类型的文件就是我们最常使用的txt文件,这类型的文件可以用记事本或WordPad等文书编辑软件来编辑;
        第二种是RTF类型,其表示法为"text/rtf",这种类型的文件特色是能对文字内容做字体缩放、变形、上色等特殊效果;
        第三类是HTML类型,也就是我们在网络上所浏览的网页类型,其表示法为"text/html",这类文件的特色相信大家都非常的清楚,除了在对字体效果的表现之外还具有在文件
        内加入图片、超级链接等相关功能。但是JEditorPane并不是一个全功能的Web Browser,它仅能支持简单的HTML语法.JEditorPane支持HTML类型的文件最主要的用途是用来制作在线辅助说明文件。
        */
        
        /*javax.swing组件*/
        JEditorPane textPane;
        JLabel messageLable;        //contentPane的SOUTH
        JTextField urlField;        //URL单行输入框
        JFileChooser fileChooser;     //文件选择器
        
        /*前进和后退,在Button初始化要用到,在监听事件也要用到,所以作为成员变量*/
        JButton backButton;
        JButton farwardButton;
        
        java.util.List history = new ArrayList();        //保存历史记录的列表
        int currentHistoryPage = -1;                                //当前页面在历史记录列表中的位置
        //属于类仅有一个且为常量,类初始化时已经在内存中生成不可变,不管新建多少个浏览器对象实例,所有浏览器对象打开窗口的总数仅保留最新MAX_HISTORY条
        public static final int MAX_HISTORY = 50;        //历史记录列表超出该值时,按顺序清除多余的历史记录
        //属于类仅有一个,所有类对象实例共用同一个该静态变量
        static int numBrowserWindows = 0;                        //当前已经打开的浏览器窗口数
        
        //标识当所有浏览器窗口都关闭,是否退出程序
        private static boolean exitWhenLastWindowClosed = false ;
        String home = "http://www.google.cn/";            //默认的主页
        
        //构造函数
        public WebBrowser(){
            //super的调用必须是构造器中的第一个语句
            super("WebBrowser");        //构造一个具有指定标题的,默认最初不可见的Frame对象
            textPane = new JEditorPane();        //设置显示HTML的面板,并设置为不可编辑
            textPane.setEditable(false);
            textPane.addHyperlinkListener(this);                    //注册事件处理器,用于超链接事件
            textPane.addPropertyChangeListener(this);            //注册事件处理器,用于处理属性改变事件。当页面加载完成时,触发该事件
            
            this.getContentPane().add(new JScrollPane(textPane), BorderLayout.CENTER);
            messageLable = new JLabel();
            this.getContentPane().add(messageLable, BorderLayout.SOUTH);
            this.initMenu();
            this.initToolBar();
            //浏览器窗口加1
            //numBrowserWindows是属于类的,在创建WebBrowser对象实例前已经在内存中生成
            WebBrowser.numBrowserWindows++;
            //当关闭窗口时,调用close方法处理(Y)
            this.addWindowListener(new WindowAdapter(){
                public void windowClosing(WindowEvent e){
                    close();
                    }
                });
            }
        
        //初始化菜单栏,只允许子类继承和重写    
        public  void initMenu(){
            JMenu fileMenu = new JMenu("文件");
            //Alt+F
            fileMenu.setMnemonic('F');
            JMenuItem newMenuItem = new JMenuItem("新建");
            //先Alt+F,再N/Alt+N,快捷键有分层级,子菜单的快捷键不能直接使用
            newMenuItem.setMnemonic('N');
            //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
            newMenuItem.addActionListener(new ActionListener(){
                //实现该接口的抽象方法
                    public void actionPerformed(ActionEvent e){
                        newBrowser();
                        }
                });
            
            JMenuItem openMenuItem = new JMenuItem("打开");
            //先Alt+F,再O/Alt+O,快捷键有分层级,子菜单的快捷键不能直接使用
    //        openMenuItem.setMnemonic('O');
            openMenuItem.setMnemonic(KeyEvent.VK_O);
            //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
            openMenuItem.addActionListener(new ActionListener(){
                //实现该接口的抽象方法
                    public void actionPerformed(ActionEvent e){
                        openLocalPage();
                        }
                });
            
            JMenuItem closeMenuItem = new JMenuItem("关闭");
            //先Alt+F,再C/Alt+C,快捷键有分层级,子菜单的快捷键不能直接使用
            closeMenuItem.setMnemonic('C');
            //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
            closeMenuItem.addActionListener(new ActionListener(){
                //实现该接口的抽象方法
                    public void actionPerformed(ActionEvent e){
                        close();
                        }
                });
            
            JMenuItem exitMenuItem = new JMenuItem("退出");
            //先Alt+F,再E/Alt+E,快捷键有分层级,子菜单的快捷键不能直接使用
            exitMenuItem.setMnemonic('E');
            //匿名内部类继承一个父类或者实现一个接口,ActionListener为接口(Y)
            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("帮助");
            helpMenu.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 exit(){
            if(JOptionPane.    showConfirmDialog(this, "你确定退出Web浏览器?", "退出",     JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){
                System.exit(0);
                }
            }
        
        @SuppressWarnings("deprecation")
        private void openLocalPage(){
            if(fileChooser==null){
                fileChooser = new JFileChooser();
                //FileFilter为抽象类,使用内部类创建一个子类实例,实现FileFilter类的抽象方法(Y)
                FileFilter fileFilter = new FileFilter(){
                    //File参数是文件过滤器对应类型的文件
                    public  boolean    accept(File f){
                        String fileName = f.getName();
                        if((fileName.endsWith("html"))||(fileName.endsWith("htm"))){
                            return true;
                            }else{return false;}
                        }
                    public String    getDescription(){
                        return "HTML Files";
                        }
                    };
                //设置当前页面默认的文件筛选器    
                fileChooser.setFileFilter(fileFilter);
                //当前页面的默认文件筛选器为系统默认的,仅表示把指定的文件筛选器添加到文件筛选器列表中
                fileChooser.addChoosableFileFilter(fileFilter);
                }
            //Pops up an "Open File" file chooser dialog,在"文件"选择器界面,如果点击"打开"按钮则返回0,如果点击"取消"或"X"按钮则返回1,其他异常返回-1
            int openResult = fileChooser.showOpenDialog(null);    //返回值为0
            System.out.println("openResult: "+openResult);
            if(openResult==JFileChooser.APPROVE_OPTION){
                //仅支持选择单个文件,支持选择多个文件使用getSelectedFiles()
                File selectFile = fileChooser.getSelectedFile();
                System.out.println(selectFile.toString());
                try{
                    //选择的本地文件向网页文件一样打开
                    displayPage(selectFile.toURL());
                }catch(MalformedURLException e){
                    e.printStackTrace();
                    }
                }
            }
        public void setHome(String home){
            this.home = home;
            }    
            
        public String getHome(){
    //        return this.home;
            return home;
            }    
        
        //打开多个浏览器窗口,是否一个窗口最后一个页面关闭,所有窗口都会一并关闭??    
    //    public static void setExitWhenLastWindowClosed(boolean b){
    //        exitWhenLastWindowClosed = b;
    //        }    
        private void newBrowser(){
            //构造函数递归调用
            WebBrowser b = new WebBrowser();
            //this指外层构造函数生成的对象实例
            b.setSize(this.getWidth(),this.getHeight());
            b.setVisible(true);
            }    
            
        //初始化工具栏,只允许子类继承和重写
        protected void initToolBar(){
            backButton = new JButton("后退");
            backButton.setEnabled(true);
            //匿名内部类为接口(Y)
            backButton.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    back();
                    }
                });
                
            farwardButton = new JButton("前进");
            farwardButton.setEnabled(true);
            //(Y)
            farwardButton.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    forward();
                    }
                });
                
            JButton refresh = new JButton("刷新");
            refresh.setEnabled(true);
            //(Y)
            refresh.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    refresh();
                    }
                });
                
            JButton home = new JButton("主页");    
            home.setEnabled(true);
            //(Y)
            home.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    home();
                    }
                });
            
            urlField = new JTextField();
            //(Y)
            urlField.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e){
                    displayPage(urlField.getText());
                    }
                });
                
            JToolBar toolBar = new     JToolBar();
            toolBar.add(backButton);
            toolBar.add(farwardButton);
            toolBar.add(refresh);
            toolBar.add(home);
            toolBar.add(new JLabel("   地址:"));
            toolBar.add(urlField);
            this.getContentPane().add(toolBar,BorderLayout.NORTH);
            }
        
        private void home(){
            displayPage(getHome());
            }
        
        private void refresh(){
            if(currentHistoryPage != -1){
                //先展示一个默认的HTMLDocument页面
                textPane.setDocument(new HTMLDocument());
                }
            visit((URL)history.get(currentHistoryPage));
            }    
        
        private void forward(){
            if(currentHistoryPage < (history.size()-1)){
                visit((URL)history.get(++currentHistoryPage));
                }
            backButton.setEnabled((currentHistoryPage > 0));
            farwardButton.setEnabled((currentHistoryPage < (history.size()-1)));
            }    
        
        private void back(){
            if(currentHistoryPage > 0){
                visit((URL)history.get(--currentHistoryPage));
            }
            backButton.setEnabled((currentHistoryPage > 0));
            farwardButton.setEnabled((currentHistoryPage < (history.size()-1)));
            }
            
        private boolean visit(URL url){
            try{
                String href = url.toString();
                startAnimation("加载" + href + "...");
                textPane.setPage(href);        //Sets the current URL being displayed,加载完毕后触发addPropertyChangeListener事件
                this.setTitle(href);
                urlField.setText(href);
                return true;
            }catch(IOException e){
                stopAnimation();
                messageLable.setText("不能打开页面" + e.getMessage());
                return false;
                }
            }
        
        @SuppressWarnings("unchecked")    
        private void displayPage(URL url){
            if(visit(url)){
                this.history.add(url);
                int numentries = history.size();
                System.out.println("numentries:" + numentries);
                for(int i=0;i<numentries;i++){
                    System.out.println("history["+i+"] : " + history.get(i));
                    }
                if(numentries > (MAX_HISTORY + 10)){
                    history = history.subList((numentries - MAX_HISTORY), numentries);
                    currentHistoryPage = MAX_HISTORY;
                    }
                currentHistoryPage =     (numentries - 1);
                //当前打开的页面会是最后一个吗?
                if(currentHistoryPage > 0){
                    backButton.setEnabled(true);
                    }
                }
            }    
            
        public void displayPage(String href){
            try{
                if(!href.startsWith("http://")){
                href = "http://"+href;
                }
                displayPage(new URL(href));
            }catch(MalformedURLException e){
                messageLable.setText("错误的网址:" + href);
                }
            }
            
        public void close(){
            //隐藏当前窗口
            this.setVisible(false);
            //销毁当前窗口的所有组件
            this.dispose();
            synchronized (WebBrowser.class){
                //浏览器窗口减1
                WebBrowser.numBrowserWindows--;
                //当Window监听器监听到关闭窗口事件,exitWhenLastWindowClosed标识默认为false,如果希望符合下面条件时关闭,则要提前通过setter设置
                if((numBrowserWindows==0) && (exitWhenLastWindowClosed==true)){
                    System.exit(0);
                    }
                }
            }
        //动画消息,显示在最底下的状态栏标签上,用于反馈浏览器状态    
        String animationMessage;
        //动画当前帧的索引
        int ainimationFrame = 0;
        //动画用到的帧,是一些字符
        String[] animationFrames = new String[]{"-", "\", "|", "/", "-", "\", "|", "/",",", ".", "o", "0", "O", "#", "*", "+"};
        //新建一个Swing的定时器,每125ms更新一次状态栏标签的文本(Y)
        javax.swing.Timer animator = new javax.swing.Timer(125,new ActionListener(){
            public void actionPerformed(ActionEvent e){
                animate();
                }
            });
        //定时器启动后就一直不间断的执行任务    
        private void animate(){
            String frame = animationFrames[ainimationFrame++];
            messageLable.setText(animationMessage + " "+ frame);
            //循环遍历动画用到的所有帧
            ainimationFrame = ainimationFrame % animationFrames.length;
            }    
        private void startAnimation(String message){
            animationMessage = message;
            ainimationFrame = 0;
            animator.start();
            }    
            
        private void stopAnimation(){
            System.out.println("信息标签停止播放动画!");
            animator.stop();
            messageLable.setText(" ");
            }
            
        public static void setExitWhenLastWindowClosed(boolean exitWhenLastWindowClosed){
            WebBrowser.exitWhenLastWindowClosed = exitWhenLastWindowClosed;
            }
            
        //实现HyperlinkListener接口的hyperlinkUpdate方法
        public void hyperlinkUpdate(HyperlinkEvent e){
            System.out.println("HyperlinkEvent.getURL(): " + e.getURL());
            HyperlinkEvent.EventType type = e.getEventType();
    //        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
    //        System.out.println(df.format(new Date())+" type: " + type);
            //激活类型--光标点击超链接位置
            if(type==HyperlinkEvent.EventType.ACTIVATED){
                displayPage(e.getURL());
                }
            //输入类型--光标放到超链接位置
            else if(type==HyperlinkEvent.EventType.ENTERED){
                messageLable.setText(e.getURL().toString());
                }
            //退出的类型--光标移出超链接位置    
            else if(type==HyperlinkEvent.EventType.EXITED){
                messageLable.setText(" ");
                }    
            }
            
        //实现PropertyChangeListener接口的propertyChange方法
        public void propertyChange(PropertyChangeEvent evt){
            System.out.println("PropertyName: "+evt.getPropertyName());
            //直到页面加载成功,之前都是对页面展示的准备,所有页面属性都是由JEditorPane完成,由PropertyChangeListener监听
            if(evt.getPropertyName().equals("page")){
                stopAnimation();
                }
            }
            
        public static void main(String[] args){
            WebBrowser.setExitWhenLastWindowClosed(true);
            WebBrowser browser = new WebBrowser();
            //获取屏幕分辨率,
    //        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    //        browser.setSize(screenSize);
            browser.setSize(800,700);
            browser.setVisible(true);
            browser.displayPage(browser.getHome());
            }    
        }

    加载页面:

  • 相关阅读:
    AC自动机 [模板]
    ChonSu [ZOJ 2684]
    Quad Tiling [POJ 3420]
    LCA 最近公共祖先 [POJ 1330]
    强连通分量[trajan]
    高斯消元 [模板]
    01K Code [HDU 1545]
    Cycle Game [ZOJ 2686]
    清除Eclipse中的内置浏览器中的历史记录(REF)
    第三方的 NET 数据库连接提供者,Lightswitch
  • 原文地址:https://www.cnblogs.com/celine/p/9905268.html
Copyright © 2020-2023  润新知