zoukankan      html  css  js  c++  java
  • 精简版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());
            }    
        }

    加载页面:

  • 相关阅读:
    suse12安装详解
    Centos7上部署openstack mitaka配置详解(将疑难点都进行划分)
    菜鸟帮你跳过openstack配置过程中的坑[文末新添加福利]
    openstack中dashboard页面RuntimeError: Unable to create a new session key. It is likely that the cache is unavailable.
    Multiple network matches found for name 'selfservice', use an ID to be more specific.报错
    查看 SELinux状态及关闭SELinux
    SELinux深入理解
    IP地址、子网掩码、网络号、主机号、网络地址、主机地址
    Oracle job procedure 存储过程定时任务
    POI文件导出至EXCEL,并弹出下载框
  • 原文地址:https://www.cnblogs.com/celine/p/9905268.html
Copyright © 2011-2022 走看看